diff --git a/spring-cloud-alibaba-dubbo/pom.xml b/spring-cloud-alibaba-dubbo/pom.xml index 9d4ce7991..df606fd6b 100644 --- a/spring-cloud-alibaba-dubbo/pom.xml +++ b/spring-cloud-alibaba-dubbo/pom.xml @@ -14,7 +14,7 @@ Spring Cloud Alibaba Dubbo - 2.7.0 + 2.7.1 2.1.0.RELEASE 2.1.0.RELEASE 4.0.1 diff --git a/spring-cloud-alibaba-dubbo/src/main/java/org/springframework/cloud/alibaba/dubbo/autoconfigure/DubboMetadataAutoConfiguration.java b/spring-cloud-alibaba-dubbo/src/main/java/org/springframework/cloud/alibaba/dubbo/autoconfigure/DubboMetadataAutoConfiguration.java index 2264e98bc..7eff2f818 100644 --- a/spring-cloud-alibaba-dubbo/src/main/java/org/springframework/cloud/alibaba/dubbo/autoconfigure/DubboMetadataAutoConfiguration.java +++ b/spring-cloud-alibaba-dubbo/src/main/java/org/springframework/cloud/alibaba/dubbo/autoconfigure/DubboMetadataAutoConfiguration.java @@ -73,7 +73,7 @@ public class DubboMetadataAutoConfiguration { } @Bean - public Supplier dubboProtocolConfigSupplier(Collection protocols) { + public Supplier dubboProtocolConfigSupplier(ObjectProvider> protocols) { return new DubboProtocolConfigSupplier(protocols); } diff --git a/spring-cloud-alibaba-dubbo/src/main/java/org/springframework/cloud/alibaba/dubbo/autoconfigure/DubboServiceRegistrationAutoConfiguration.java b/spring-cloud-alibaba-dubbo/src/main/java/org/springframework/cloud/alibaba/dubbo/autoconfigure/DubboServiceRegistrationAutoConfiguration.java index 8fe92e9f6..c926fd6b4 100644 --- a/spring-cloud-alibaba-dubbo/src/main/java/org/springframework/cloud/alibaba/dubbo/autoconfigure/DubboServiceRegistrationAutoConfiguration.java +++ b/spring-cloud-alibaba-dubbo/src/main/java/org/springframework/cloud/alibaba/dubbo/autoconfigure/DubboServiceRegistrationAutoConfiguration.java @@ -17,16 +17,20 @@ package org.springframework.cloud.alibaba.dubbo.autoconfigure; import org.apache.dubbo.common.URL; -import org.apache.dubbo.config.spring.context.event.ServiceBeanExportedEvent; import com.ecwid.consul.v1.agent.model.NewService; +import org.aspectj.lang.ProceedingJoinPoint; +import org.aspectj.lang.annotation.Around; +import org.aspectj.lang.annotation.Aspect; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.springframework.aop.support.AopUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.autoconfigure.AutoConfigureAfter; import org.springframework.boot.autoconfigure.AutoConfigureOrder; import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.boot.context.event.ApplicationStartedEvent; import org.springframework.cloud.alibaba.dubbo.metadata.repository.DubboServiceMetadataRepository; import org.springframework.cloud.alibaba.dubbo.registry.DubboServiceRegistrationEventPublishingAspect; import org.springframework.cloud.alibaba.dubbo.registry.event.ServiceInstancePreRegisteredEvent; @@ -35,7 +39,6 @@ import org.springframework.cloud.client.ServiceInstance; import org.springframework.cloud.client.serviceregistry.Registration; import org.springframework.cloud.client.serviceregistry.ServiceRegistry; import org.springframework.cloud.consul.serviceregistry.ConsulRegistration; -import org.springframework.context.ApplicationContext; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Import; import org.springframework.context.event.EventListener; @@ -49,6 +52,7 @@ import java.util.stream.Collectors; import static org.springframework.cloud.alibaba.dubbo.autoconfigure.DubboServiceRegistrationAutoConfiguration.CONSUL_AUTO_CONFIGURATION_CLASS_NAME; import static org.springframework.cloud.alibaba.dubbo.autoconfigure.DubboServiceRegistrationAutoConfiguration.EUREKA_AUTO_CONFIGURATION_CLASS_NAME; +import static org.springframework.cloud.alibaba.dubbo.registry.DubboServiceRegistrationEventPublishingAspect.REGISTER_POINTCUT_EXPRESSION; import static org.springframework.cloud.alibaba.dubbo.registry.SpringCloudRegistry.DUBBO_URLS_METADATA_PROPERTY_NAME; /** @@ -74,7 +78,7 @@ public class DubboServiceRegistrationAutoConfiguration { public static final String CONSUL_AUTO_CONFIGURATION_CLASS_NAME = "org.springframework.cloud.consul.serviceregistry.ConsulAutoServiceRegistrationAutoConfiguration"; - private static final String CONSUL_AUTO_REGISTRATION_CLASS_NAME = + public static final String CONSUL_AUTO_REGISTRATION_CLASS_NAME = "org.springframework.cloud.consul.serviceregistry.ConsulAutoRegistration"; private static final Logger logger = LoggerFactory.getLogger(DubboServiceRegistrationAutoConfiguration.class); @@ -95,32 +99,29 @@ public class DubboServiceRegistrationAutoConfiguration { @Configuration @ConditionalOnBean(name = EUREKA_AUTO_CONFIGURATION_CLASS_NAME) @AutoConfigureOrder - static class EurekaConfiguration { - - @Autowired - private ApplicationContext applicationContext; + @Aspect + class EurekaConfiguration { @Autowired private ServiceRegistry serviceRegistry; - private volatile Registration registration; + private Registration registration; + private boolean deferredRegistration = true; - @EventListener(ServiceBeanExportedEvent.class) - public void onServiceBeanExported() { - reRegister(); - } - - private void reRegister() { - if (registration == null) { - return; + @Around(REGISTER_POINTCUT_EXPRESSION) + public Object doRegister(ProceedingJoinPoint pjp, Registration registration) throws Throwable { + this.registration = registration; + if (deferredRegistration) { + return null; } - serviceRegistry.register(registration); + return pjp.proceed(pjp.getArgs()); } - @EventListener(ServiceInstancePreRegisteredEvent.class) - public void onServiceInstancePreRegistered(ServiceInstancePreRegisteredEvent event) { - registration = event.getSource(); + @EventListener(ApplicationStartedEvent.class) + public void onApplicationStarted() { + deferredRegistration = false; + serviceRegistry.register(registration); } } @@ -138,17 +139,22 @@ public class DubboServiceRegistrationAutoConfiguration { @EventListener(ServiceInstancePreRegisteredEvent.class) public void onServiceInstancePreRegistered(ServiceInstancePreRegisteredEvent event) { Registration registration = event.getSource(); - String registrationClassName = registration.getClass().getName(); + Class registrationClass = AopUtils.getTargetClass(registration); + String registrationClassName = registrationClass.getName(); if (CONSUL_AUTO_REGISTRATION_CLASS_NAME.equalsIgnoreCase(registrationClassName)) { - NewService newService = ((ConsulRegistration) registration).getService(); - String dubboURLsJson = getDubboURLsJSON(); - if (StringUtils.hasText(dubboURLsJson)) { - List tags = newService.getTags(); - tags.add(DUBBO_URLS_METADATA_PROPERTY_NAME + "=" + dubboURLsJson); - } + ConsulRegistration consulRegistration = (ConsulRegistration) registration; + attachURLsIntoMetadata(consulRegistration); } } + private void attachURLsIntoMetadata(ConsulRegistration consulRegistration) { + NewService newService = consulRegistration.getService(); + String dubboURLsJson = getDubboURLsJSON(); + if (StringUtils.hasText(dubboURLsJson)) { + List tags = newService.getTags(); + tags.add(DUBBO_URLS_METADATA_PROPERTY_NAME + "=" + dubboURLsJson); + } + } } private void attachURLsIntoMetadata(Registration registration) { diff --git a/spring-cloud-alibaba-dubbo/src/main/java/org/springframework/cloud/alibaba/dubbo/autoconfigure/DubboServiceRegistrationNonWebApplicationAutoConfiguration.java b/spring-cloud-alibaba-dubbo/src/main/java/org/springframework/cloud/alibaba/dubbo/autoconfigure/DubboServiceRegistrationNonWebApplicationAutoConfiguration.java new file mode 100644 index 000000000..3f69e7ad8 --- /dev/null +++ b/spring-cloud-alibaba-dubbo/src/main/java/org/springframework/cloud/alibaba/dubbo/autoconfigure/DubboServiceRegistrationNonWebApplicationAutoConfiguration.java @@ -0,0 +1,156 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.cloud.alibaba.dubbo.autoconfigure; + +import org.apache.dubbo.common.URL; +import org.apache.dubbo.config.spring.ServiceBean; +import org.apache.dubbo.config.spring.context.event.ServiceBeanExportedEvent; + +import com.ecwid.consul.v1.agent.model.NewService; +import org.aspectj.lang.ProceedingJoinPoint; +import org.aspectj.lang.annotation.Around; +import org.aspectj.lang.annotation.Aspect; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.autoconfigure.AutoConfigureAfter; +import org.springframework.boot.autoconfigure.AutoConfigureOrder; +import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; +import org.springframework.boot.autoconfigure.condition.ConditionalOnNotWebApplication; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.cloud.alibaba.dubbo.registry.event.ServiceInstancePreRegisteredEvent; +import org.springframework.cloud.client.ServiceInstance; +import org.springframework.cloud.client.serviceregistry.Registration; +import org.springframework.cloud.client.serviceregistry.ServiceRegistry; +import org.springframework.cloud.consul.serviceregistry.ConsulAutoRegistration; +import org.springframework.cloud.consul.serviceregistry.ConsulRegistration; +import org.springframework.cloud.netflix.eureka.CloudEurekaInstanceConfig; +import org.springframework.cloud.netflix.eureka.serviceregistry.EurekaRegistration; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.event.EventListener; + +import java.util.List; + +import static org.springframework.cloud.alibaba.dubbo.autoconfigure.DubboServiceRegistrationAutoConfiguration.CONSUL_AUTO_CONFIGURATION_CLASS_NAME; +import static org.springframework.cloud.alibaba.dubbo.autoconfigure.DubboServiceRegistrationAutoConfiguration.EUREKA_AUTO_CONFIGURATION_CLASS_NAME; + +/** + * Dubbo Service Registration Auto-{@link Configuration} for Non-Web application + * + * @author Mercy + */ +@Configuration +@ConditionalOnNotWebApplication +@ConditionalOnProperty(value = "spring.cloud.service-registry.auto-registration.enabled", matchIfMissing = true) +@AutoConfigureAfter(DubboServiceRegistrationAutoConfiguration.class) +@Aspect +public class DubboServiceRegistrationNonWebApplicationAutoConfiguration { + + @Autowired + private ServiceRegistry serviceRegistry; + + @Autowired + private Registration registration; + + private volatile Integer webPort = null; + + private volatile boolean registered = false; + + @Around("execution(* org.springframework.cloud.client.serviceregistry.Registration.getPort())") + public Object getPort(ProceedingJoinPoint pjp) throws Throwable { + return webPort != null ? webPort : pjp.proceed(); + } + + @EventListener(ServiceBeanExportedEvent.class) + public void onServiceBeanExported(ServiceBeanExportedEvent event) { + setWebPort(event.getServiceBean()); + register(); + } + + private void register() { + if (registered) { + return; + } + serviceRegistry.register(registration); + registered = true; + } + + /** + * Set web port from {@link ServiceBean#getExportedUrls() exported URLs} if "rest" protocol is present. + * + * @param serviceBean {@link ServiceBean} + */ + private void setWebPort(ServiceBean serviceBean) { + if (webPort == null) { + List urls = serviceBean.getExportedUrls(); + urls.stream() + .filter(url -> "rest".equalsIgnoreCase(url.getProtocol())) + .findFirst() + .ifPresent(url -> { + webPort = url.getPort(); + }); + } + } + + @Configuration + @ConditionalOnBean(name = EUREKA_AUTO_CONFIGURATION_CLASS_NAME) + @AutoConfigureOrder + static class EurekaConfiguration { + + @EventListener(ServiceInstancePreRegisteredEvent.class) + public void onServiceInstancePreRegistered(ServiceInstancePreRegisteredEvent event) { + setPort(event.getSource()); + } + + private void setPort(Registration registration) { + EurekaRegistration eurekaRegistration = (EurekaRegistration) registration; + CloudEurekaInstanceConfig cloudEurekaInstanceConfig = eurekaRegistration.getInstanceConfig(); + cloudEurekaInstanceConfig.setNonSecurePort(registration.getPort()); + } + + } + + @Configuration + @ConditionalOnBean(name = CONSUL_AUTO_CONFIGURATION_CLASS_NAME) + @AutoConfigureOrder + class ConsulConfiguration { + + /** + * Handle the pre-registered event of {@link ServiceInstance} for Consul + * + * @param event {@link ServiceInstancePreRegisteredEvent} + */ + @EventListener(ServiceInstancePreRegisteredEvent.class) + public void onServiceInstancePreRegistered(ServiceInstancePreRegisteredEvent event) { + Registration registration = event.getSource(); + ConsulAutoRegistration consulRegistration = (ConsulAutoRegistration) registration; + setPort(consulRegistration); + } + + /** + * Set port on Non-Web Application + * + * @param consulRegistration {@link ConsulRegistration} + */ + private void setPort(ConsulAutoRegistration consulRegistration) { + int port = consulRegistration.getPort(); + NewService newService = consulRegistration.getService(); + if (newService.getPort() == null) { + newService.setPort(port); + } + } + } + +} diff --git a/spring-cloud-alibaba-dubbo/src/main/java/org/springframework/cloud/alibaba/dubbo/metadata/DubboProtocolConfigSupplier.java b/spring-cloud-alibaba-dubbo/src/main/java/org/springframework/cloud/alibaba/dubbo/metadata/DubboProtocolConfigSupplier.java index 5eb3adfbe..d5d994303 100644 --- a/spring-cloud-alibaba-dubbo/src/main/java/org/springframework/cloud/alibaba/dubbo/metadata/DubboProtocolConfigSupplier.java +++ b/spring-cloud-alibaba-dubbo/src/main/java/org/springframework/cloud/alibaba/dubbo/metadata/DubboProtocolConfigSupplier.java @@ -18,6 +18,8 @@ package org.springframework.cloud.alibaba.dubbo.metadata; import org.apache.dubbo.config.ProtocolConfig; +import org.springframework.beans.factory.ObjectProvider; + import java.util.Collection; import java.util.Iterator; import java.util.function.Supplier; @@ -31,15 +33,16 @@ import static org.apache.dubbo.common.Constants.DEFAULT_PROTOCOL; */ public class DubboProtocolConfigSupplier implements Supplier { - private final Collection protocols; + private final ObjectProvider> protocols; - public DubboProtocolConfigSupplier(Collection protocols) { + public DubboProtocolConfigSupplier(ObjectProvider> protocols) { this.protocols = protocols; } @Override public ProtocolConfig get() { ProtocolConfig protocolConfig = null; + Collection protocols = this.protocols.getIfAvailable(); for (ProtocolConfig protocol : protocols) { String protocolName = protocol.getName(); if (DEFAULT_PROTOCOL.equals(protocolName)) { diff --git a/spring-cloud-alibaba-dubbo/src/main/java/org/springframework/cloud/alibaba/dubbo/registry/DubboServiceRegistrationEventPublishingAspect.java b/spring-cloud-alibaba-dubbo/src/main/java/org/springframework/cloud/alibaba/dubbo/registry/DubboServiceRegistrationEventPublishingAspect.java index ca05d837b..17826624f 100644 --- a/spring-cloud-alibaba-dubbo/src/main/java/org/springframework/cloud/alibaba/dubbo/registry/DubboServiceRegistrationEventPublishingAspect.java +++ b/spring-cloud-alibaba-dubbo/src/main/java/org/springframework/cloud/alibaba/dubbo/registry/DubboServiceRegistrationEventPublishingAspect.java @@ -39,7 +39,7 @@ public class DubboServiceRegistrationEventPublishingAspect implements Applicatio /** * The pointcut expression for {@link ServiceRegistry#register(Registration)} */ - private static final String REGISTER_POINTCUT_EXPRESSION = + public static final String REGISTER_POINTCUT_EXPRESSION = "execution(* org.springframework.cloud.client.serviceregistry.ServiceRegistry.register(*)) && args(registration)"; private ApplicationEventPublisher applicationEventPublisher; diff --git a/spring-cloud-alibaba-dubbo/src/main/resources/META-INF/spring.factories b/spring-cloud-alibaba-dubbo/src/main/resources/META-INF/spring.factories index 572cee86b..6f0ffd963 100644 --- a/spring-cloud-alibaba-dubbo/src/main/resources/META-INF/spring.factories +++ b/spring-cloud-alibaba-dubbo/src/main/resources/META-INF/spring.factories @@ -2,6 +2,7 @@ org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ org.springframework.cloud.alibaba.dubbo.autoconfigure.DubboMetadataAutoConfiguration,\ org.springframework.cloud.alibaba.dubbo.autoconfigure.DubboOpenFeignAutoConfiguration,\ org.springframework.cloud.alibaba.dubbo.autoconfigure.DubboServiceRegistrationAutoConfiguration,\ + org.springframework.cloud.alibaba.dubbo.autoconfigure.DubboServiceRegistrationNonWebApplicationAutoConfiguration,\ org.springframework.cloud.alibaba.dubbo.autoconfigure.DubboLoadBalancedRestTemplateAutoConfiguration,\ org.springframework.cloud.alibaba.dubbo.autoconfigure.DubboServiceAutoConfiguration diff --git a/spring-cloud-alibaba-examples/spring-cloud-alibaba-dubbo-examples/spring-cloud-dubbo-consumer-sample/src/main/java/org/springframework/cloud/alibaba/dubbo/bootstrap/DubboSpringCloudConsumerBootstrap.java b/spring-cloud-alibaba-examples/spring-cloud-alibaba-dubbo-examples/spring-cloud-dubbo-consumer-sample/src/main/java/org/springframework/cloud/alibaba/dubbo/bootstrap/DubboSpringCloudConsumerBootstrap.java index 8c2a0c9eb..2e389ce25 100644 --- a/spring-cloud-alibaba-examples/spring-cloud-alibaba-dubbo-examples/spring-cloud-dubbo-consumer-sample/src/main/java/org/springframework/cloud/alibaba/dubbo/bootstrap/DubboSpringCloudConsumerBootstrap.java +++ b/spring-cloud-alibaba-examples/spring-cloud-alibaba-dubbo-examples/spring-cloud-dubbo-consumer-sample/src/main/java/org/springframework/cloud/alibaba/dubbo/bootstrap/DubboSpringCloudConsumerBootstrap.java @@ -17,6 +17,7 @@ package org.springframework.cloud.alibaba.dubbo.bootstrap; import org.apache.dubbo.config.annotation.Reference; + import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.ApplicationRunner; @@ -52,7 +53,7 @@ import static org.springframework.http.MediaType.APPLICATION_JSON_UTF8_VALUE; @EnableFeignClients public class DubboSpringCloudConsumerBootstrap { - @Reference(version = "1.0.0") + @Reference(version = "1.0.0", protocol = "dubbo") private RestService restService; @Autowired @@ -94,7 +95,7 @@ public class DubboSpringCloudConsumerBootstrap { } @FeignClient("${provider.application.name}") - @DubboTransported() + @DubboTransported(protocol = "dubbo") public interface DubboFeignRestService { @GetMapping(value = "/param") diff --git a/spring-cloud-alibaba-examples/spring-cloud-alibaba-dubbo-examples/spring-cloud-dubbo-consumer-sample/src/main/resources/application.yaml b/spring-cloud-alibaba-examples/spring-cloud-alibaba-dubbo-examples/spring-cloud-dubbo-consumer-sample/src/main/resources/application.yaml index 263a56997..41c671461 100644 --- a/spring-cloud-alibaba-examples/spring-cloud-alibaba-dubbo-examples/spring-cloud-dubbo-consumer-sample/src/main/resources/application.yaml +++ b/spring-cloud-alibaba-examples/spring-cloud-alibaba-dubbo-examples/spring-cloud-dubbo-consumer-sample/src/main/resources/application.yaml @@ -9,4 +9,4 @@ server: provider: application: - name: spring-cloud-alibaba-dubbo-web-provider \ No newline at end of file + name: spring-cloud-alibaba-dubbo-provider \ No newline at end of file diff --git a/spring-cloud-alibaba-examples/spring-cloud-alibaba-dubbo-examples/spring-cloud-dubbo-provider-sample/pom.xml b/spring-cloud-alibaba-examples/spring-cloud-alibaba-dubbo-examples/spring-cloud-dubbo-provider-sample/pom.xml index 68832a50d..9c43a453a 100644 --- a/spring-cloud-alibaba-examples/spring-cloud-alibaba-dubbo-examples/spring-cloud-dubbo-provider-sample/pom.xml +++ b/spring-cloud-alibaba-examples/spring-cloud-alibaba-dubbo-examples/spring-cloud-dubbo-provider-sample/pom.xml @@ -17,6 +17,13 @@ + + + javax.servlet + javax.servlet-api + 3.1.0 + + org.springframework diff --git a/spring-cloud-alibaba-examples/spring-cloud-alibaba-dubbo-examples/spring-cloud-dubbo-provider-sample/src/main/java/org/springframework/cloud/alibaba/dubbo/bootstrap/DubboSpringCloudProviderBootstrap.java b/spring-cloud-alibaba-examples/spring-cloud-alibaba-dubbo-examples/spring-cloud-dubbo-provider-sample/src/main/java/org/springframework/cloud/alibaba/dubbo/bootstrap/DubboSpringCloudProviderBootstrap.java index 4606a190d..8e6ed4e99 100644 --- a/spring-cloud-alibaba-examples/spring-cloud-alibaba-dubbo-examples/spring-cloud-dubbo-provider-sample/src/main/java/org/springframework/cloud/alibaba/dubbo/bootstrap/DubboSpringCloudProviderBootstrap.java +++ b/spring-cloud-alibaba-examples/spring-cloud-alibaba-dubbo-examples/spring-cloud-dubbo-provider-sample/src/main/java/org/springframework/cloud/alibaba/dubbo/bootstrap/DubboSpringCloudProviderBootstrap.java @@ -16,6 +16,7 @@ */ package org.springframework.cloud.alibaba.dubbo.bootstrap; +import org.springframework.boot.WebApplicationType; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.builder.SpringApplicationBuilder; import org.springframework.cloud.client.discovery.EnableDiscoveryClient; @@ -30,6 +31,7 @@ public class DubboSpringCloudProviderBootstrap { public static void main(String[] args) { new SpringApplicationBuilder(DubboSpringCloudProviderBootstrap.class) .properties("spring.profiles.active=nacos") + .web(WebApplicationType.NONE) .run(args); } }