diff --git a/spring-cloud-alibaba-dubbo/src/main/java/org/springframework/cloud/alibaba/dubbo/autoconfigure/DubboLoadBalancedRestTemplateAutoConfiguration.java b/spring-cloud-alibaba-dubbo/src/main/java/org/springframework/cloud/alibaba/dubbo/autoconfigure/DubboLoadBalancedRestTemplateAutoConfiguration.java index 6eea3233..f32bea75 100644 --- a/spring-cloud-alibaba-dubbo/src/main/java/org/springframework/cloud/alibaba/dubbo/autoconfigure/DubboLoadBalancedRestTemplateAutoConfiguration.java +++ b/spring-cloud-alibaba-dubbo/src/main/java/org/springframework/cloud/alibaba/dubbo/autoconfigure/DubboLoadBalancedRestTemplateAutoConfiguration.java @@ -27,15 +27,19 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.context.event.ApplicationStartedEvent; import org.springframework.cloud.alibaba.dubbo.annotation.DubboTransported; import org.springframework.cloud.alibaba.dubbo.client.loadbalancer.DubboAdapterLoadBalancerInterceptor; +import org.springframework.cloud.alibaba.dubbo.metadata.DubboTransportedMetadata; import org.springframework.cloud.alibaba.dubbo.metadata.repository.DubboServiceMetadataRepository; +import org.springframework.cloud.alibaba.dubbo.metadata.service.DubboGenericServiceFactory; import org.springframework.cloud.client.loadbalancer.LoadBalanced; import org.springframework.cloud.client.loadbalancer.LoadBalancerAutoConfiguration; import org.springframework.cloud.client.loadbalancer.LoadBalancerInterceptor; import org.springframework.cloud.client.loadbalancer.RestTemplateCustomizer; import org.springframework.context.annotation.Configuration; import org.springframework.context.event.EventListener; +import org.springframework.core.env.Environment; import org.springframework.core.type.MethodMetadata; import org.springframework.http.client.ClientHttpRequestInterceptor; +import org.springframework.util.CollectionUtils; import org.springframework.web.client.RestTemplate; import java.util.ArrayList; @@ -66,6 +70,12 @@ public class DubboLoadBalancedRestTemplateAutoConfiguration implements BeanClass @Autowired private ConfigurableListableBeanFactory beanFactory; + @Autowired + private DubboGenericServiceFactory dubboGenericServiceFactory; + + @Autowired + private Environment environment; + @LoadBalanced @Autowired(required = false) private Map restTemplates = Collections.emptyMap(); @@ -82,37 +92,43 @@ public class DubboLoadBalancedRestTemplateAutoConfiguration implements BeanClass public void adaptRestTemplates() { for (Map.Entry entry : restTemplates.entrySet()) { String beanName = entry.getKey(); - if (isDubboTranslatedAnnotated(beanName)) { - adaptRestTemplate(entry.getValue()); + Map dubboTranslatedAttributes = getDubboTranslatedAttributes(beanName); + if (!CollectionUtils.isEmpty(dubboTranslatedAttributes)) { + adaptRestTemplate(entry.getValue(), dubboTranslatedAttributes); } } } /** - * Judge {@link RestTemplate} bean being annotated {@link DubboTransported @DubboTransported} or not + * Gets the annotation attributes {@link RestTemplate} bean being annotated + * {@link DubboTransported @DubboTransported} * * @param beanName the bean name of {@link LoadBalanced @LoadBalanced} {@link RestTemplate} - * @return + * @return non-null {@link Map} */ - private boolean isDubboTranslatedAnnotated(String beanName) { - boolean annotated = false; + private Map getDubboTranslatedAttributes(String beanName) { + Map attributes = Collections.emptyMap(); BeanDefinition beanDefinition = beanFactory.getBeanDefinition(beanName); if (beanDefinition instanceof AnnotatedBeanDefinition) { AnnotatedBeanDefinition annotatedBeanDefinition = (AnnotatedBeanDefinition) beanDefinition; MethodMetadata factoryMethodMetadata = annotatedBeanDefinition.getFactoryMethodMetadata(); - annotated = factoryMethodMetadata != null && - !factoryMethodMetadata.getAnnotationAttributes(DUBBO_TRANSPORTED_CLASS_NAME).isEmpty(); + attributes = factoryMethodMetadata != null ? + factoryMethodMetadata.getAnnotationAttributes(DUBBO_TRANSPORTED_CLASS_NAME) : Collections.emptyMap(); } - return annotated; + return attributes; } /** * Adapt the instance of {@link DubboAdapterLoadBalancerInterceptor} to the {@link LoadBalancerInterceptor} Bean. * - * @param restTemplate {@link LoadBalanced @LoadBalanced} {@link RestTemplate} Bean + * @param restTemplate {@link LoadBalanced @LoadBalanced} {@link RestTemplate} Bean + * @param dubboTranslatedAttributes the annotation dubboTranslatedAttributes {@link RestTemplate} bean being annotated + * {@link DubboTransported @DubboTransported} */ - private void adaptRestTemplate(RestTemplate restTemplate) { + private void adaptRestTemplate(RestTemplate restTemplate, Map dubboTranslatedAttributes) { + + DubboTransportedMetadata dubboTransportedMetadata = buildDubboTransportedMetadata(dubboTranslatedAttributes); List interceptors = new ArrayList<>(restTemplate.getInterceptors()); @@ -120,12 +136,23 @@ public class DubboLoadBalancedRestTemplateAutoConfiguration implements BeanClass if (index > -1) { interceptors.set(index, new DubboAdapterLoadBalancerInterceptor(repository, loadBalancerInterceptor, - restTemplate.getMessageConverters(),classLoader)); + restTemplate.getMessageConverters(), classLoader, + dubboTransportedMetadata, dubboGenericServiceFactory)); } restTemplate.setInterceptors(interceptors); } + private DubboTransportedMetadata buildDubboTransportedMetadata(Map dubboTranslatedAttributes) { + DubboTransportedMetadata dubboTransportedMetadata = new DubboTransportedMetadata(); + String protocol = (String) dubboTranslatedAttributes.get("protocol"); + String cluster = (String) dubboTranslatedAttributes.get("cluster"); + // resolve placeholders + dubboTransportedMetadata.setProtocol(environment.resolvePlaceholders(protocol)); + dubboTransportedMetadata.setCluster(environment.resolvePlaceholders(cluster)); + return dubboTransportedMetadata; + } + @Override public void setBeanClassLoader(ClassLoader classLoader) { this.classLoader = classLoader; diff --git a/spring-cloud-alibaba-dubbo/src/main/java/org/springframework/cloud/alibaba/dubbo/autoconfigure/DubboOpenFeignAutoConfiguration.java b/spring-cloud-alibaba-dubbo/src/main/java/org/springframework/cloud/alibaba/dubbo/autoconfigure/DubboOpenFeignAutoConfiguration.java index a3d208c9..ab4c7825 100644 --- a/spring-cloud-alibaba-dubbo/src/main/java/org/springframework/cloud/alibaba/dubbo/autoconfigure/DubboOpenFeignAutoConfiguration.java +++ b/spring-cloud-alibaba-dubbo/src/main/java/org/springframework/cloud/alibaba/dubbo/autoconfigure/DubboOpenFeignAutoConfiguration.java @@ -26,6 +26,7 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean import org.springframework.cloud.alibaba.dubbo.metadata.repository.DubboServiceMetadataRepository; import org.springframework.cloud.alibaba.dubbo.metadata.resolver.DubboServiceBeanMetadataResolver; import org.springframework.cloud.alibaba.dubbo.metadata.resolver.MetadataResolver; +import org.springframework.cloud.alibaba.dubbo.metadata.service.DubboGenericServiceFactory; import org.springframework.cloud.alibaba.dubbo.openfeign.TargeterBeanPostProcessor; import org.springframework.cloud.openfeign.FeignAutoConfiguration; import org.springframework.context.annotation.Bean; @@ -54,8 +55,9 @@ public class DubboOpenFeignAutoConfiguration { @Bean public TargeterBeanPostProcessor targeterBeanPostProcessor(Environment environment, - DubboServiceMetadataRepository dubboServiceMetadataRepository) { - return new TargeterBeanPostProcessor(environment, dubboServiceMetadataRepository); + DubboServiceMetadataRepository dubboServiceMetadataRepository, + DubboGenericServiceFactory dubboGenericServiceFactory) { + return new TargeterBeanPostProcessor(environment, dubboServiceMetadataRepository,dubboGenericServiceFactory); } } \ No newline at end of file diff --git a/spring-cloud-alibaba-dubbo/src/main/java/org/springframework/cloud/alibaba/dubbo/autoconfigure/DubboServiceAutoConfiguration.java b/spring-cloud-alibaba-dubbo/src/main/java/org/springframework/cloud/alibaba/dubbo/autoconfigure/DubboServiceAutoConfiguration.java new file mode 100644 index 00000000..551cd65e --- /dev/null +++ b/spring-cloud-alibaba-dubbo/src/main/java/org/springframework/cloud/alibaba/dubbo/autoconfigure/DubboServiceAutoConfiguration.java @@ -0,0 +1,38 @@ +/* + * 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.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; +import org.springframework.cloud.alibaba.dubbo.metadata.service.DubboGenericServiceFactory; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +/** + * Spring Boot Auto-Configuration class for Dubbo Service + * + * @author Mercy + */ +@Configuration +public class DubboServiceAutoConfiguration { + + @Bean + @ConditionalOnMissingBean + public DubboGenericServiceFactory dubboGenericServiceFactory() { + return new DubboGenericServiceFactory(); + } + +} \ No newline at end of file diff --git a/spring-cloud-alibaba-dubbo/src/main/java/org/springframework/cloud/alibaba/dubbo/client/loadbalancer/DubboAdapterLoadBalancerInterceptor.java b/spring-cloud-alibaba-dubbo/src/main/java/org/springframework/cloud/alibaba/dubbo/client/loadbalancer/DubboAdapterLoadBalancerInterceptor.java index 089504ec..d40892bc 100644 --- a/spring-cloud-alibaba-dubbo/src/main/java/org/springframework/cloud/alibaba/dubbo/client/loadbalancer/DubboAdapterLoadBalancerInterceptor.java +++ b/spring-cloud-alibaba-dubbo/src/main/java/org/springframework/cloud/alibaba/dubbo/client/loadbalancer/DubboAdapterLoadBalancerInterceptor.java @@ -16,15 +16,17 @@ */ package org.springframework.cloud.alibaba.dubbo.client.loadbalancer; -import com.alibaba.dubbo.config.spring.ReferenceBean; import com.alibaba.dubbo.rpc.service.GenericException; import com.alibaba.dubbo.rpc.service.GenericService; +import org.springframework.cloud.alibaba.dubbo.metadata.DubboServiceMetadata; +import org.springframework.cloud.alibaba.dubbo.metadata.DubboTransportedMetadata; import org.springframework.cloud.alibaba.dubbo.metadata.MethodMetadata; import org.springframework.cloud.alibaba.dubbo.metadata.RequestMetadata; import org.springframework.cloud.alibaba.dubbo.metadata.RestMethodMetadata; import org.springframework.cloud.alibaba.dubbo.metadata.repository.DubboServiceMetadataRepository; import org.springframework.cloud.alibaba.dubbo.metadata.resolver.ParameterResolver; +import org.springframework.cloud.alibaba.dubbo.metadata.service.DubboGenericServiceFactory; import org.springframework.cloud.client.loadbalancer.LoadBalancerInterceptor; import org.springframework.http.HttpRequest; import org.springframework.http.client.ClientHttpRequestExecution; @@ -52,18 +54,23 @@ public class DubboAdapterLoadBalancerInterceptor implements ClientHttpRequestInt private final LoadBalancerInterceptor loadBalancerInterceptor; - private final List> messageConverters; - private final DubboClientHttpResponseFactory clientHttpResponseFactory; + private final DubboTransportedMetadata dubboTransportedMetadata; + + private final DubboGenericServiceFactory dubboGenericServiceFactory; + public DubboAdapterLoadBalancerInterceptor(DubboServiceMetadataRepository dubboServiceMetadataRepository, LoadBalancerInterceptor loadBalancerInterceptor, List> messageConverters, - ClassLoader classLoader) { + ClassLoader classLoader, + DubboTransportedMetadata dubboTransportedMetadata, + DubboGenericServiceFactory dubboGenericServiceFactory) { this.repository = dubboServiceMetadataRepository; this.loadBalancerInterceptor = loadBalancerInterceptor; - this.messageConverters = messageConverters; + this.dubboTransportedMetadata = dubboTransportedMetadata; this.clientHttpResponseFactory = new DubboClientHttpResponseFactory(messageConverters, classLoader); + this.dubboGenericServiceFactory = dubboGenericServiceFactory; } @Override @@ -79,19 +86,21 @@ public class DubboAdapterLoadBalancerInterceptor implements ClientHttpRequestInt RequestMetadata clientMetadata = buildRequestMetadata(request, uriComponents); - RestMethodMetadata restMethodMetadata = repository.getRestMethodMetadata(serviceName, clientMetadata); + DubboServiceMetadata dubboServiceMetadata = repository.get(serviceName, clientMetadata); - ReferenceBean referenceBean = repository.getReferenceBean(serviceName, clientMetadata); - - if (referenceBean == null || restMethodMetadata == null) { + if (dubboServiceMetadata == null) { // if DubboServiceMetadata is not found return loadBalancerInterceptor.intercept(request, body, execution); } + RestMethodMetadata restMethodMetadata = dubboServiceMetadata.getRestMethodMetadata(); + + GenericService genericService = dubboGenericServiceFactory.create(dubboServiceMetadata, dubboTransportedMetadata); + Object result = null; GenericException exception = null; try { - result = invokeService(restMethodMetadata, referenceBean, clientMetadata); + result = invokeService(restMethodMetadata, genericService, clientMetadata); } catch (GenericException e) { exception = e; } @@ -99,7 +108,7 @@ public class DubboAdapterLoadBalancerInterceptor implements ClientHttpRequestInt return clientHttpResponseFactory.build(result, exception, clientMetadata, restMethodMetadata); } - private Object invokeService(RestMethodMetadata restMethodMetadata, ReferenceBean referenceBean, + private Object invokeService(RestMethodMetadata restMethodMetadata, GenericService genericService, RequestMetadata clientMetadata) throws GenericException { MethodMetadata methodMetadata = restMethodMetadata.getMethod(); @@ -110,8 +119,6 @@ public class DubboAdapterLoadBalancerInterceptor implements ClientHttpRequestInt Object[] parameters = parameterResolver.resolveParameters(restMethodMetadata, clientMetadata); - GenericService genericService = referenceBean.get(); - Object result = genericService.$invoke(methodName, parameterTypes, parameters); return result; diff --git a/spring-cloud-alibaba-dubbo/src/main/java/org/springframework/cloud/alibaba/dubbo/metadata/DubboServiceMetadata.java b/spring-cloud-alibaba-dubbo/src/main/java/org/springframework/cloud/alibaba/dubbo/metadata/DubboServiceMetadata.java new file mode 100644 index 00000000..f245df09 --- /dev/null +++ b/spring-cloud-alibaba-dubbo/src/main/java/org/springframework/cloud/alibaba/dubbo/metadata/DubboServiceMetadata.java @@ -0,0 +1,58 @@ +/* + * 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.metadata; + +import java.util.Objects; + +/** + * Dubbo Service Metadata + * + * @author Mercy + */ +public class DubboServiceMetadata { + + private final ServiceRestMetadata serviceRestMetadata; + + private final RestMethodMetadata restMethodMetadata; + + public DubboServiceMetadata(ServiceRestMetadata serviceRestMetadata, RestMethodMetadata restMethodMetadata) { + this.serviceRestMetadata = serviceRestMetadata; + this.restMethodMetadata = restMethodMetadata; + } + + public ServiceRestMetadata getServiceRestMetadata() { + return serviceRestMetadata; + } + + public RestMethodMetadata getRestMethodMetadata() { + return restMethodMetadata; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (!(o instanceof DubboServiceMetadata)) return false; + DubboServiceMetadata that = (DubboServiceMetadata) o; + return Objects.equals(serviceRestMetadata, that.serviceRestMetadata) && + Objects.equals(restMethodMetadata, that.restMethodMetadata); + } + + @Override + public int hashCode() { + return Objects.hash(serviceRestMetadata, restMethodMetadata); + } +} diff --git a/spring-cloud-alibaba-dubbo/src/main/java/org/springframework/cloud/alibaba/dubbo/metadata/DubboTransportedMetadata.java b/spring-cloud-alibaba-dubbo/src/main/java/org/springframework/cloud/alibaba/dubbo/metadata/DubboTransportedMetadata.java new file mode 100644 index 00000000..2811bdaf --- /dev/null +++ b/spring-cloud-alibaba-dubbo/src/main/java/org/springframework/cloud/alibaba/dubbo/metadata/DubboTransportedMetadata.java @@ -0,0 +1,61 @@ +/* + * 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.metadata; + +import org.springframework.cloud.alibaba.dubbo.annotation.DubboTransported; + +import java.util.Objects; + +/** + * {@link DubboTransported @DubboTransported} Metadata + */ +public class DubboTransportedMetadata { + + private String protocol; + + private String cluster; + + public String getProtocol() { + return protocol; + } + + public void setProtocol(String protocol) { + this.protocol = protocol; + } + + public String getCluster() { + return cluster; + } + + public void setCluster(String cluster) { + this.cluster = cluster; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (!(o instanceof DubboTransportedMetadata)) return false; + DubboTransportedMetadata that = (DubboTransportedMetadata) o; + return Objects.equals(protocol, that.protocol) && + Objects.equals(cluster, that.cluster); + } + + @Override + public int hashCode() { + return Objects.hash(protocol, cluster); + } +} diff --git a/spring-cloud-alibaba-dubbo/src/main/java/org/springframework/cloud/alibaba/dubbo/metadata/DubboTransportedMethodMetadata.java b/spring-cloud-alibaba-dubbo/src/main/java/org/springframework/cloud/alibaba/dubbo/metadata/DubboTransportedMethodMetadata.java index e12c0201..ade65aa9 100644 --- a/spring-cloud-alibaba-dubbo/src/main/java/org/springframework/cloud/alibaba/dubbo/metadata/DubboTransportedMethodMetadata.java +++ b/spring-cloud-alibaba-dubbo/src/main/java/org/springframework/cloud/alibaba/dubbo/metadata/DubboTransportedMethodMetadata.java @@ -19,55 +19,88 @@ package org.springframework.cloud.alibaba.dubbo.metadata; import org.springframework.cloud.alibaba.dubbo.annotation.DubboTransported; import java.lang.reflect.Method; +import java.util.List; +import java.util.Objects; /** * {@link MethodMetadata} annotated {@link DubboTransported @DubboTransported} * * @author Mercy */ -public class DubboTransportedMethodMetadata extends MethodMetadata { +public class DubboTransportedMethodMetadata { - private String protocol; + private final DubboTransportedMetadata dubboTransportedMetadata; - private String cluster; + private final MethodMetadata methodMetadata; public DubboTransportedMethodMetadata(Method method) { - super(method); + this.methodMetadata = new MethodMetadata(method); + this.dubboTransportedMetadata = new DubboTransportedMetadata(); } public String getProtocol() { - return protocol; + return dubboTransportedMetadata.getProtocol(); } public void setProtocol(String protocol) { - this.protocol = protocol; + dubboTransportedMetadata.setProtocol(protocol); } public String getCluster() { - return cluster; + return dubboTransportedMetadata.getCluster(); } public void setCluster(String cluster) { - this.cluster = cluster; + dubboTransportedMetadata.setCluster(cluster); + } + + public String getName() { + return methodMetadata.getName(); + } + + public void setName(String name) { + methodMetadata.setName(name); + } + + public String getReturnType() { + return methodMetadata.getReturnType(); + } + + public void setReturnType(String returnType) { + methodMetadata.setReturnType(returnType); + } + + public List getParams() { + return methodMetadata.getParams(); + } + + public void setParams(List params) { + methodMetadata.setParams(params); + } + + public Method getMethod() { + return methodMetadata.getMethod(); + } + + public DubboTransportedMetadata getDubboTransportedMetadata() { + return dubboTransportedMetadata; + } + + public MethodMetadata getMethodMetadata() { + return methodMetadata; } @Override public boolean equals(Object o) { if (this == o) return true; if (!(o instanceof DubboTransportedMethodMetadata)) return false; - if (!super.equals(o)) return false; - DubboTransportedMethodMetadata that = (DubboTransportedMethodMetadata) o; - - if (protocol != null ? !protocol.equals(that.protocol) : that.protocol != null) return false; - return cluster != null ? cluster.equals(that.cluster) : that.cluster == null; + return Objects.equals(dubboTransportedMetadata, that.dubboTransportedMetadata) && + Objects.equals(methodMetadata, that.methodMetadata); } @Override public int hashCode() { - int result = super.hashCode(); - result = 31 * result + (protocol != null ? protocol.hashCode() : 0); - result = 31 * result + (cluster != null ? cluster.hashCode() : 0); - return result; + return Objects.hash(dubboTransportedMetadata, methodMetadata); } } diff --git a/spring-cloud-alibaba-dubbo/src/main/java/org/springframework/cloud/alibaba/dubbo/metadata/RestMethodMetadata.java b/spring-cloud-alibaba-dubbo/src/main/java/org/springframework/cloud/alibaba/dubbo/metadata/RestMethodMetadata.java index 3f971880..46675b47 100644 --- a/spring-cloud-alibaba-dubbo/src/main/java/org/springframework/cloud/alibaba/dubbo/metadata/RestMethodMetadata.java +++ b/spring-cloud-alibaba-dubbo/src/main/java/org/springframework/cloud/alibaba/dubbo/metadata/RestMethodMetadata.java @@ -20,13 +20,14 @@ import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonProperty; import java.util.Collection; -import java.util.Collections; import java.util.List; import java.util.Map; import java.util.Objects; /** * Method Request Metadata + * + * @author Mercy */ @JsonInclude(JsonInclude.Include.NON_NULL) public class RestMethodMetadata { diff --git a/spring-cloud-alibaba-dubbo/src/main/java/org/springframework/cloud/alibaba/dubbo/metadata/repository/DubboServiceMetadataRepository.java b/spring-cloud-alibaba-dubbo/src/main/java/org/springframework/cloud/alibaba/dubbo/metadata/repository/DubboServiceMetadataRepository.java index 30cb0cdb..cb578bd2 100644 --- a/spring-cloud-alibaba-dubbo/src/main/java/org/springframework/cloud/alibaba/dubbo/metadata/repository/DubboServiceMetadataRepository.java +++ b/spring-cloud-alibaba-dubbo/src/main/java/org/springframework/cloud/alibaba/dubbo/metadata/repository/DubboServiceMetadataRepository.java @@ -16,15 +16,12 @@ */ package org.springframework.cloud.alibaba.dubbo.metadata.repository; -import com.alibaba.dubbo.config.spring.ReferenceBean; -import com.alibaba.dubbo.rpc.service.GenericService; - import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.cloud.alibaba.dubbo.http.matcher.RequestMetadataMatcher; +import org.springframework.cloud.alibaba.dubbo.metadata.DubboServiceMetadata; import org.springframework.cloud.alibaba.dubbo.metadata.RequestMetadata; -import org.springframework.cloud.alibaba.dubbo.metadata.RestMethodMetadata; import org.springframework.cloud.alibaba.dubbo.metadata.ServiceRestMetadata; import org.springframework.cloud.alibaba.dubbo.metadata.service.MetadataConfigService; import org.springframework.http.HttpRequest; @@ -35,10 +32,6 @@ import java.util.Map; import java.util.Set; import static org.springframework.cloud.alibaba.dubbo.http.DefaultHttpRequest.builder; -import static org.springframework.cloud.alibaba.dubbo.registry.SpringCloudRegistry.getServiceGroup; -import static org.springframework.cloud.alibaba.dubbo.registry.SpringCloudRegistry.getServiceInterface; -import static org.springframework.cloud.alibaba.dubbo.registry.SpringCloudRegistry.getServiceSegments; -import static org.springframework.cloud.alibaba.dubbo.registry.SpringCloudRegistry.getServiceVersion; import static org.springframework.util.CollectionUtils.isEmpty; /** @@ -53,15 +46,9 @@ public class DubboServiceMetadataRepository { /** * Key is application name - * Value is Map> + * Value is Map */ - private Map>> referenceBeansRepository = newHashMap(); - - /** - * Key is application name - * Value is Map - */ - private Map> restMethodMetadataRepository = newHashMap(); + private Map> repository = newHashMap(); @Autowired private MetadataConfigService metadataConfigService; @@ -73,7 +60,7 @@ public class DubboServiceMetadataRepository { */ public void initialize(String serviceName) { - if (referenceBeansRepository.containsKey(serviceName)) { + if (repository.containsKey(serviceName)) { return; } @@ -87,29 +74,28 @@ public class DubboServiceMetadataRepository { return; } - Map> genericServicesMap = getReferenceBeansMap(serviceName); - - Map restMethodMetadataMap = getRestMethodMetadataMap(serviceName); + Map metadataMap = getMetadataMap(serviceName); for (ServiceRestMetadata serviceRestMetadata : serviceRestMetadataSet) { - ReferenceBean referenceBean = adaptReferenceBean(serviceRestMetadata); - serviceRestMetadata.getMeta().forEach(restMethodMetadata -> { RequestMetadata requestMetadata = restMethodMetadata.getRequest(); RequestMetadataMatcher matcher = new RequestMetadataMatcher(requestMetadata); - genericServicesMap.put(matcher, referenceBean); - restMethodMetadataMap.put(matcher, restMethodMetadata); + DubboServiceMetadata metadata = new DubboServiceMetadata(serviceRestMetadata, restMethodMetadata); + metadataMap.put(matcher, metadata); }); } } - public ReferenceBean getReferenceBean(String serviceName, RequestMetadata requestMetadata) { - return match(referenceBeansRepository, serviceName, requestMetadata); - } - - public RestMethodMetadata getRestMethodMetadata(String serviceName, RequestMetadata requestMetadata) { - return match(restMethodMetadataRepository, serviceName, requestMetadata); + /** + * Get a {@link DubboServiceMetadata} by the specified service name if {@link RequestMetadata} matched + * + * @param serviceName service name + * @param requestMetadata {@link RequestMetadata} to be matched + * @return {@link DubboServiceMetadata} if matched, or null + */ + public DubboServiceMetadata get(String serviceName, RequestMetadata requestMetadata) { + return match(repository, serviceName, requestMetadata); } private static T match(Map> repository, String serviceName, @@ -140,28 +126,8 @@ public class DubboServiceMetadataRepository { return object; } - private ReferenceBean adaptReferenceBean(ServiceRestMetadata serviceRestMetadata) { - String dubboServiceName = serviceRestMetadata.getName(); - String[] segments = getServiceSegments(dubboServiceName); - String interfaceName = getServiceInterface(segments); - String version = getServiceVersion(segments); - String group = getServiceGroup(segments); - - ReferenceBean referenceBean = new ReferenceBean(); - referenceBean.setGeneric(true); - referenceBean.setInterface(interfaceName); - referenceBean.setVersion(version); - referenceBean.setGroup(group); - - return referenceBean; - } - - private Map> getReferenceBeansMap(String serviceName) { - return getMap(referenceBeansRepository, serviceName); - } - - private Map getRestMethodMetadataMap(String serviceName) { - return getMap(restMethodMetadataRepository, serviceName); + private Map getMetadataMap(String serviceName) { + return getMap(repository, serviceName); } private static Map getMap(Map> repository, String key) { diff --git a/spring-cloud-alibaba-dubbo/src/main/java/org/springframework/cloud/alibaba/dubbo/metadata/service/DubboGenericServiceFactory.java b/spring-cloud-alibaba-dubbo/src/main/java/org/springframework/cloud/alibaba/dubbo/metadata/service/DubboGenericServiceFactory.java new file mode 100644 index 00000000..fbdf19c2 --- /dev/null +++ b/spring-cloud-alibaba-dubbo/src/main/java/org/springframework/cloud/alibaba/dubbo/metadata/service/DubboGenericServiceFactory.java @@ -0,0 +1,79 @@ +/* + * 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.metadata.service; + +import com.alibaba.dubbo.config.spring.ReferenceBean; +import com.alibaba.dubbo.rpc.service.GenericService; + +import org.springframework.cloud.alibaba.dubbo.metadata.DubboServiceMetadata; +import org.springframework.cloud.alibaba.dubbo.metadata.DubboTransportedMetadata; +import org.springframework.cloud.alibaba.dubbo.metadata.ServiceRestMetadata; + +import java.util.Objects; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; + +import static org.springframework.cloud.alibaba.dubbo.registry.SpringCloudRegistry.getServiceGroup; +import static org.springframework.cloud.alibaba.dubbo.registry.SpringCloudRegistry.getServiceInterface; +import static org.springframework.cloud.alibaba.dubbo.registry.SpringCloudRegistry.getServiceSegments; +import static org.springframework.cloud.alibaba.dubbo.registry.SpringCloudRegistry.getServiceVersion; + +/** + * Dubbo {@link GenericService} Factory + * + * @author Mercy + */ +public class DubboGenericServiceFactory { + + private final ConcurrentMap cache = new ConcurrentHashMap<>(); + + public GenericService create(DubboServiceMetadata dubboServiceMetadata, + DubboTransportedMetadata dubboTransportedMetadata) { + + Integer key = Objects.hash(dubboServiceMetadata, dubboTransportedMetadata); + + GenericService genericService = cache.get(key); + + if (genericService == null) { + genericService = build(dubboServiceMetadata.getServiceRestMetadata(), dubboTransportedMetadata); + cache.putIfAbsent(key, genericService); + } + + return genericService; + } + + + private GenericService build(ServiceRestMetadata serviceRestMetadata, + DubboTransportedMetadata dubboTransportedMetadata) { + String dubboServiceName = serviceRestMetadata.getName(); + String[] segments = getServiceSegments(dubboServiceName); + String interfaceName = getServiceInterface(segments); + String version = getServiceVersion(segments); + String group = getServiceGroup(segments); + + ReferenceBean referenceBean = new ReferenceBean(); + referenceBean.setGeneric(true); + referenceBean.setInterface(interfaceName); + referenceBean.setVersion(version); + referenceBean.setGroup(group); + referenceBean.setProtocol(dubboTransportedMetadata.getProtocol()); + referenceBean.setCluster(dubboTransportedMetadata.getCluster()); + + return referenceBean.get(); + } + +} diff --git a/spring-cloud-alibaba-dubbo/src/main/java/org/springframework/cloud/alibaba/dubbo/openfeign/TargeterBeanPostProcessor.java b/spring-cloud-alibaba-dubbo/src/main/java/org/springframework/cloud/alibaba/dubbo/openfeign/TargeterBeanPostProcessor.java index ecd17c77..7bb51221 100644 --- a/spring-cloud-alibaba-dubbo/src/main/java/org/springframework/cloud/alibaba/dubbo/openfeign/TargeterBeanPostProcessor.java +++ b/spring-cloud-alibaba-dubbo/src/main/java/org/springframework/cloud/alibaba/dubbo/openfeign/TargeterBeanPostProcessor.java @@ -20,6 +20,7 @@ import org.springframework.beans.BeansException; import org.springframework.beans.factory.BeanClassLoaderAware; import org.springframework.beans.factory.config.BeanPostProcessor; import org.springframework.cloud.alibaba.dubbo.metadata.repository.DubboServiceMetadataRepository; +import org.springframework.cloud.alibaba.dubbo.metadata.service.DubboGenericServiceFactory; import org.springframework.core.env.Environment; import static java.lang.reflect.Proxy.newProxyInstance; @@ -39,12 +40,16 @@ public class TargeterBeanPostProcessor implements BeanPostProcessor, BeanClassLo private final DubboServiceMetadataRepository dubboServiceMetadataRepository; + private final DubboGenericServiceFactory dubboGenericServiceFactory; + private ClassLoader classLoader; public TargeterBeanPostProcessor(Environment environment, - DubboServiceMetadataRepository dubboServiceMetadataRepository) { + DubboServiceMetadataRepository dubboServiceMetadataRepository, + DubboGenericServiceFactory dubboGenericServiceFactory) { this.environment = environment; this.dubboServiceMetadataRepository = dubboServiceMetadataRepository; + this.dubboGenericServiceFactory = dubboGenericServiceFactory; } @Override @@ -58,7 +63,8 @@ public class TargeterBeanPostProcessor implements BeanPostProcessor, BeanClassLo Class targetClass = resolveClassName(TARGETER_CLASS_NAME, classLoader); if (targetClass.isAssignableFrom(beanClass)) { return newProxyInstance(classLoader, new Class[]{targetClass}, - new TargeterInvocationHandler(bean, environment, dubboServiceMetadataRepository)); + new TargeterInvocationHandler(bean, environment, dubboServiceMetadataRepository, + dubboGenericServiceFactory)); } return bean; } diff --git a/spring-cloud-alibaba-dubbo/src/main/java/org/springframework/cloud/alibaba/dubbo/openfeign/TargeterInvocationHandler.java b/spring-cloud-alibaba-dubbo/src/main/java/org/springframework/cloud/alibaba/dubbo/openfeign/TargeterInvocationHandler.java index a86a51d7..346837aa 100644 --- a/spring-cloud-alibaba-dubbo/src/main/java/org/springframework/cloud/alibaba/dubbo/openfeign/TargeterInvocationHandler.java +++ b/spring-cloud-alibaba-dubbo/src/main/java/org/springframework/cloud/alibaba/dubbo/openfeign/TargeterInvocationHandler.java @@ -17,16 +17,18 @@ package org.springframework.cloud.alibaba.dubbo.openfeign; -import com.alibaba.dubbo.config.spring.ReferenceBean; import com.alibaba.dubbo.rpc.service.GenericService; import feign.Contract; import feign.Target; +import org.springframework.cloud.alibaba.dubbo.metadata.DubboServiceMetadata; +import org.springframework.cloud.alibaba.dubbo.metadata.DubboTransportedMetadata; import org.springframework.cloud.alibaba.dubbo.metadata.DubboTransportedMethodMetadata; import org.springframework.cloud.alibaba.dubbo.metadata.RequestMetadata; import org.springframework.cloud.alibaba.dubbo.metadata.RestMethodMetadata; import org.springframework.cloud.alibaba.dubbo.metadata.repository.DubboServiceMetadataRepository; import org.springframework.cloud.alibaba.dubbo.metadata.resolver.DubboTransportedMethodMetadataResolver; +import org.springframework.cloud.alibaba.dubbo.metadata.service.DubboGenericServiceFactory; import org.springframework.cloud.openfeign.FeignContext; import org.springframework.core.env.Environment; @@ -51,11 +53,14 @@ class TargeterInvocationHandler implements InvocationHandler { private final DubboServiceMetadataRepository repository; - TargeterInvocationHandler(Object bean, Environment environment, - DubboServiceMetadataRepository repository) { + private final DubboGenericServiceFactory dubboGenericServiceFactory; + + TargeterInvocationHandler(Object bean, Environment environment, DubboServiceMetadataRepository repository, + DubboGenericServiceFactory dubboGenericServiceFactory) { this.bean = bean; this.environment = environment; this.repository = repository; + this.dubboGenericServiceFactory = dubboGenericServiceFactory; } @Override @@ -115,12 +120,12 @@ class TargeterInvocationHandler implements InvocationHandler { Map genericServicesMap = new HashMap<>(); methodRequestMetadataMap.forEach((dubboTransportedMethodMetadata, requestMetadata) -> { - ReferenceBean referenceBean = repository.getReferenceBean(serviceName, requestMetadata); - RestMethodMetadata restMethodMetadata = repository.getRestMethodMetadata(serviceName, requestMetadata); + DubboServiceMetadata dubboServiceMetadata = repository.get(serviceName, requestMetadata); + RestMethodMetadata restMethodMetadata = dubboServiceMetadata.getRestMethodMetadata(); org.springframework.cloud.alibaba.dubbo.metadata.MethodMetadata methodMetadata = restMethodMetadata.getMethod(); - referenceBean.setProtocol(dubboTransportedMethodMetadata.getProtocol()); - referenceBean.setCluster(dubboTransportedMethodMetadata.getCluster()); - genericServicesMap.put(dubboTransportedMethodMetadata.getMethod(), referenceBean.get()); + DubboTransportedMetadata dubboTransportedMetadata = dubboTransportedMethodMetadata.getDubboTransportedMetadata(); + GenericService genericService = dubboGenericServiceFactory.create(dubboServiceMetadata, dubboTransportedMetadata); + genericServicesMap.put(dubboTransportedMethodMetadata.getMethod(), genericService); methodMetadataMap.put(dubboTransportedMethodMetadata.getMethod(), methodMetadata); }); 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 b0e37c9c..516f25f6 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,7 +2,8 @@ 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.DubboRestMetadataRegistrationAutoConfiguration,\ - org.springframework.cloud.alibaba.dubbo.autoconfigure.DubboLoadBalancedRestTemplateAutoConfiguration + org.springframework.cloud.alibaba.dubbo.autoconfigure.DubboLoadBalancedRestTemplateAutoConfiguration,\ + org.springframework.cloud.alibaba.dubbo.autoconfigure.DubboServiceAutoConfiguration org.springframework.context.ApplicationContextInitializer=\ - org.springframework.cloud.alibaba.dubbo.context.DubboServiceRegistrationApplicationContextInitializer + org.springframework.cloud.alibaba.dubbo.context.DubboServiceRegistrationApplicationContextInitializer \ No newline at end of file