From fd1150f3b243e978437018d2bb9cd6ccf57e14e3 Mon Sep 17 00:00:00 2001 From: mercyblitz Date: Thu, 23 May 2019 13:49:11 +0800 Subject: [PATCH] Polish apache/incubator-dubbo#4071 : @Reference can't match the local @Service beans --- .../annotation/AnnotationBeanNameBuilder.java | 142 ------------------ .../ReferenceAnnotationBeanPostProcessor.java | 10 +- .../ServiceAnnotationBeanPostProcessor.java | 14 +- .../annotation/ServiceBeanNameBuilder.java | 112 ++++++++++++++ ...t.java => ServiceBeanNameBuilderTest.java} | 29 ++-- 5 files changed, 134 insertions(+), 173 deletions(-) delete mode 100644 dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/beans/factory/annotation/AnnotationBeanNameBuilder.java create mode 100644 dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/beans/factory/annotation/ServiceBeanNameBuilder.java rename dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/beans/factory/annotation/{AnnotationBeanNameBuilderTest.java => ServiceBeanNameBuilderTest.java} (67%) diff --git a/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/beans/factory/annotation/AnnotationBeanNameBuilder.java b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/beans/factory/annotation/AnnotationBeanNameBuilder.java deleted file mode 100644 index 6e18e2a3471..00000000000 --- a/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/beans/factory/annotation/AnnotationBeanNameBuilder.java +++ /dev/null @@ -1,142 +0,0 @@ -/* - * 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.apache.dubbo.config.spring.beans.factory.annotation; - -import org.apache.dubbo.common.constants.CommonConstants; -import org.apache.dubbo.config.annotation.Reference; -import org.apache.dubbo.config.annotation.Service; -import org.apache.dubbo.registry.Registry; - -import org.springframework.core.env.Environment; - -import static org.apache.dubbo.common.constants.CommonConstants.DEFAULT_PROTOCOL; -import static org.apache.dubbo.common.constants.RegistryConstants.CONSUMERS_CATEGORY; -import static org.apache.dubbo.common.constants.RegistryConstants.PROVIDERS_CATEGORY; -import static org.apache.dubbo.config.spring.util.AnnotationUtils.resolveInterfaceName; -import static org.springframework.util.StringUtils.arrayToCommaDelimitedString; -import static org.springframework.util.StringUtils.hasText; - -/** - * The Bean Name Builder for the annotations {@link Service} and {@link Reference} - *

- * The naming rule is consistent with the the implementation {@link Registry} that is based on the service-name aware - * infrastructure, e.g Spring Cloud, Cloud Native and so on. - *

- * The pattern of bean name : ${category}:${protocol}:${serviceInterface}:${version}:${group}. - *

- * ${version} and ${group} are optional. - * - * @since 2.6.6 - */ -class AnnotationBeanNameBuilder { - - private static final String SEPARATOR = ":"; - - // Required properties - - private final String category; - - private final String protocol; - - private final String interfaceClassName; - - // Optional properties - - private String version; - - private String group; - - private Environment environment; - - private AnnotationBeanNameBuilder(String category, String protocol, String interfaceClassName) { - this.category = category; - this.protocol = protocol; - this.interfaceClassName = interfaceClassName; - } - - private AnnotationBeanNameBuilder(Service service, Class interfaceClass) { - this(PROVIDERS_CATEGORY, resolveProtocol(service.protocol()), resolveInterfaceName(service, interfaceClass)); - this.group(service.group()); - this.version(service.version()); - } - - private AnnotationBeanNameBuilder(Reference reference, Class interfaceClass) { - this(CONSUMERS_CATEGORY, resolveProtocol(reference.protocol()), resolveInterfaceName(reference, interfaceClass)); - this.group(reference.group()); - this.version(reference.version()); - } - - public static AnnotationBeanNameBuilder create(Service service, Class interfaceClass) { - return new AnnotationBeanNameBuilder(service, interfaceClass); - } - - public static AnnotationBeanNameBuilder create(Reference reference, Class interfaceClass) { - return new AnnotationBeanNameBuilder(reference, interfaceClass); - } - - private static void append(StringBuilder builder, String value) { - if (hasText(value)) { - builder.append(SEPARATOR).append(value); - } - } - - public AnnotationBeanNameBuilder group(String group) { - this.group = group; - return this; - } - - public AnnotationBeanNameBuilder version(String version) { - this.version = version; - return this; - } - - public AnnotationBeanNameBuilder environment(Environment environment) { - this.environment = environment; - return this; - } - - /** - * Resolve the protocol - * - * @param protocols one or more protocols - * @return if protocols == null, it will return - * {@link CommonConstants#DEFAULT_PROTOCOL "dubbo"} as the default protocol - * @see CommonConstants#DEFAULT_PROTOCOL - */ - private static String resolveProtocol(String... protocols) { - String protocol = arrayToCommaDelimitedString(protocols); - return hasText(protocol) ? protocol : DEFAULT_PROTOCOL; - } - - /** - * Build bean name while resolve the placeholders if possible. - * - * @return pattern : ${category}:${protocol}:${serviceInterface}:${version}:${group} - */ - public String build() { - // Append the required properties - StringBuilder beanNameBuilder = new StringBuilder(category); - append(beanNameBuilder, protocol); - append(beanNameBuilder, interfaceClassName); - // Append the optional properties - append(beanNameBuilder, version); - append(beanNameBuilder, group); - String beanName = beanNameBuilder.toString(); - // Resolve placeholders - return environment != null ? environment.resolvePlaceholders(beanName) : beanName; - } -} diff --git a/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/beans/factory/annotation/ReferenceAnnotationBeanPostProcessor.java b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/beans/factory/annotation/ReferenceAnnotationBeanPostProcessor.java index 7c3a6b9b87d..b40948de95a 100644 --- a/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/beans/factory/annotation/ReferenceAnnotationBeanPostProcessor.java +++ b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/beans/factory/annotation/ReferenceAnnotationBeanPostProcessor.java @@ -41,6 +41,8 @@ import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; +import static org.apache.dubbo.config.spring.beans.factory.annotation.ServiceBeanNameBuilder.create; + /** * {@link org.springframework.beans.factory.config.BeanPostProcessor} implementation * that Consumer service {@link Reference} annotated fields @@ -178,16 +180,14 @@ protected String buildInjectedObjectCacheKey(Reference reference, Object bean, S return buildReferencedBeanName(reference, injectedType) + "#source=" + (injectedElement.getMember()) + - "#attributes=" + AnnotationUtils.getAttributes(reference,getEnvironment(),true); + "#attributes=" + AnnotationUtils.getAttributes(reference, getEnvironment(), true); } private String buildReferencedBeanName(Reference reference, Class injectedType) { - AnnotationBeanNameBuilder builder = AnnotationBeanNameBuilder.create(reference, injectedType); - - builder.environment(getEnvironment()); + ServiceBeanNameBuilder serviceBeanNameBuilder = create(reference, injectedType, getEnvironment()); - return getEnvironment().resolvePlaceholders(builder.build()); + return serviceBeanNameBuilder.build(); } private ReferenceBean buildReferenceBeanIfAbsent(String referencedBeanName, Reference reference, diff --git a/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/beans/factory/annotation/ServiceAnnotationBeanPostProcessor.java b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/beans/factory/annotation/ServiceAnnotationBeanPostProcessor.java index 305e3724132..e12db85fa7b 100644 --- a/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/beans/factory/annotation/ServiceAnnotationBeanPostProcessor.java +++ b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/beans/factory/annotation/ServiceAnnotationBeanPostProcessor.java @@ -60,6 +60,7 @@ import java.util.Map; import java.util.Set; +import static org.apache.dubbo.config.spring.beans.factory.annotation.ServiceBeanNameBuilder.create; import static org.apache.dubbo.config.spring.util.ObjectUtils.of; import static org.springframework.beans.factory.support.BeanDefinitionBuilder.rootBeanDefinition; import static org.springframework.context.annotation.AnnotationConfigUtils.CONFIGURATION_BEAN_NAME_GENERATOR; @@ -259,7 +260,7 @@ private void registerServiceBean(BeanDefinitionHolder beanDefinitionHolder, Bean buildServiceBeanDefinition(service, interfaceClass, annotatedServiceBeanName); // ServiceBean Bean name - String beanName = generateServiceBeanName(service, interfaceClass, annotatedServiceBeanName); + String beanName = generateServiceBeanName(service, interfaceClass); if (scanner.checkCandidate(beanName, serviceBeanDefinition)) { // check duplicated candidate bean registry.registerBeanDefinition(beanName, serviceBeanDefinition); @@ -285,19 +286,14 @@ private void registerServiceBean(BeanDefinitionHolder beanDefinitionHolder, Bean * Generates the bean name of {@link ServiceBean} * * @param service - * @param interfaceClass the class of interface annotated {@link Service} - * @param annotatedServiceBeanName the bean name of annotated {@link Service} + * @param interfaceClass the class of interface annotated {@link Service} * @return ServiceBean@interfaceClassName#annotatedServiceBeanName * @since 2.5.9 */ - private String generateServiceBeanName(Service service, Class interfaceClass, String annotatedServiceBeanName) { - - AnnotationBeanNameBuilder builder = AnnotationBeanNameBuilder.create(service, interfaceClass); - - builder.environment(environment); + private String generateServiceBeanName(Service service, Class interfaceClass) { + ServiceBeanNameBuilder builder = create(service, interfaceClass, environment); return builder.build(); - } private Class resolveServiceInterfaceClass(Class annotatedServiceBeanClass, Service service) { diff --git a/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/beans/factory/annotation/ServiceBeanNameBuilder.java b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/beans/factory/annotation/ServiceBeanNameBuilder.java new file mode 100644 index 00000000000..5d272515ab3 --- /dev/null +++ b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/beans/factory/annotation/ServiceBeanNameBuilder.java @@ -0,0 +1,112 @@ +/* + * 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.apache.dubbo.config.spring.beans.factory.annotation; + +import org.apache.dubbo.config.annotation.Reference; +import org.apache.dubbo.config.annotation.Service; +import org.apache.dubbo.config.spring.ReferenceBean; +import org.apache.dubbo.config.spring.ServiceBean; + +import org.springframework.core.env.Environment; +import org.springframework.util.StringUtils; + +import static org.apache.dubbo.config.spring.util.AnnotationUtils.resolveInterfaceName; + +/** + * Dubbo {@link Service @Service} Bean Builder + * + * @see Service + * @see Reference + * @see ServiceBean + * @see ReferenceBean + * @since 2.6.5 + */ +public class ServiceBeanNameBuilder { + + private static final String SEPARATOR = ":"; + + private final String interfaceClassName; + + private final Environment environment; + + // Optional + private String version; + + private String group; + + private ServiceBeanNameBuilder(String interfaceClassName, Environment environment) { + this.interfaceClassName = interfaceClassName; + this.environment = environment; + } + + private ServiceBeanNameBuilder(Class interfaceClass, Environment environment) { + this(interfaceClass.getName(), environment); + } + + private ServiceBeanNameBuilder(Service service, Class interfaceClass, Environment environment) { + this(resolveInterfaceName(service, interfaceClass), environment); + this.group(service.group()); + this.version(service.version()); + } + + private ServiceBeanNameBuilder(Reference reference, Class interfaceClass, Environment environment) { + this(resolveInterfaceName(reference, interfaceClass), environment); + this.group(reference.group()); + this.version(reference.version()); + } + + public static ServiceBeanNameBuilder create(Class interfaceClass, Environment environment) { + return new ServiceBeanNameBuilder(interfaceClass, environment); + } + + public static ServiceBeanNameBuilder create(Service service, Class interfaceClass, Environment environment) { + return new ServiceBeanNameBuilder(service, interfaceClass, environment); + } + + public static ServiceBeanNameBuilder create(Reference reference, Class interfaceClass, Environment environment) { + return new ServiceBeanNameBuilder(reference, interfaceClass, environment); + } + + private static void append(StringBuilder builder, String value) { + if (StringUtils.hasText(value)) { + builder.append(value).append(SEPARATOR); + } + } + + public ServiceBeanNameBuilder group(String group) { + this.group = group; + return this; + } + + public ServiceBeanNameBuilder version(String version) { + this.version = version; + return this; + } + + public String build() { + StringBuilder beanNameBuilder = new StringBuilder("ServiceBean").append(SEPARATOR); + // Required + append(beanNameBuilder, interfaceClassName); + // Optional + append(beanNameBuilder, version); + append(beanNameBuilder, group); + // Build and remove last ":" + String rawBeanName = beanNameBuilder.substring(0, beanNameBuilder.length() - 1); + // Resolve placeholders + return environment.resolvePlaceholders(rawBeanName); + } +} diff --git a/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/beans/factory/annotation/AnnotationBeanNameBuilderTest.java b/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/beans/factory/annotation/ServiceBeanNameBuilderTest.java similarity index 67% rename from dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/beans/factory/annotation/AnnotationBeanNameBuilderTest.java rename to dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/beans/factory/annotation/ServiceBeanNameBuilderTest.java index 2e79109ab33..747fc1e2693 100644 --- a/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/beans/factory/annotation/AnnotationBeanNameBuilderTest.java +++ b/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/beans/factory/annotation/ServiceBeanNameBuilderTest.java @@ -27,18 +27,18 @@ import org.springframework.mock.env.MockEnvironment; import org.springframework.util.ReflectionUtils; -import static org.apache.dubbo.config.spring.beans.factory.annotation.AnnotationBeanNameBuilderTest.GROUP; -import static org.apache.dubbo.config.spring.beans.factory.annotation.AnnotationBeanNameBuilderTest.VERSION; +import static org.apache.dubbo.config.spring.beans.factory.annotation.ServiceBeanNameBuilderTest.GROUP; +import static org.apache.dubbo.config.spring.beans.factory.annotation.ServiceBeanNameBuilderTest.VERSION; /** - * {@link AnnotationBeanNameBuilder} Test + * {@link ServiceBeanNameBuilder} Test * - * @see AnnotationBeanNameBuilder + * @see ServiceBeanNameBuilder * @since 2.6.6 */ @Service(interfaceClass = DemoService.class, group = GROUP, version = VERSION, application = "application", module = "module", registry = {"1", "2", "3"}) -public class AnnotationBeanNameBuilderTest { +public class ServiceBeanNameBuilderTest { @Reference(interfaceClass = DemoService.class, group = "DUBBO", version = "${dubbo.version}", application = "application", module = "module", registry = {"1", "2", "3"}) @@ -58,25 +58,20 @@ public void prepare() { @Test public void testServiceAnnotation() { - Service service = AnnotationUtils.getAnnotation(AnnotationBeanNameBuilderTest.class, Service.class); - AnnotationBeanNameBuilder builder = AnnotationBeanNameBuilder.create(service, INTERFACE_CLASS); - Assert.assertEquals("providers:dubbo:org.apache.dubbo.config.spring.api.DemoService:1.0.0:DUBBO", + Service service = AnnotationUtils.getAnnotation(ServiceBeanNameBuilderTest.class, Service.class); + ServiceBeanNameBuilder builder = ServiceBeanNameBuilder.create(service, INTERFACE_CLASS, environment); + Assert.assertEquals("ServiceBean:org.apache.dubbo.config.spring.api.DemoService:1.0.0:DUBBO", builder.build()); - builder.environment(environment); - Assert.assertEquals("providers:dubbo:org.apache.dubbo.config.spring.api.DemoService:1.0.0:DUBBO", + Assert.assertEquals("ServiceBean:org.apache.dubbo.config.spring.api.DemoService:1.0.0:DUBBO", builder.build()); } @Test public void testReferenceAnnotation() { - Reference reference = AnnotationUtils.getAnnotation(ReflectionUtils.findField(AnnotationBeanNameBuilderTest.class, "INTERFACE_CLASS"), Reference.class); - AnnotationBeanNameBuilder builder = AnnotationBeanNameBuilder.create(reference, INTERFACE_CLASS); - Assert.assertEquals("consumers:dubbo:org.apache.dubbo.config.spring.api.DemoService:${dubbo.version}:DUBBO", - builder.build()); - - builder.environment(environment); - Assert.assertEquals("consumers:dubbo:org.apache.dubbo.config.spring.api.DemoService:1.0.0:DUBBO", + Reference reference = AnnotationUtils.getAnnotation(ReflectionUtils.findField(ServiceBeanNameBuilderTest.class, "INTERFACE_CLASS"), Reference.class); + ServiceBeanNameBuilder builder = ServiceBeanNameBuilder.create(reference, INTERFACE_CLASS, environment); + Assert.assertEquals("ServiceBean:org.apache.dubbo.config.spring.api.DemoService:1.0.0:DUBBO", builder.build()); }