This is an automated email from the ASF dual-hosted git repository. mercyblitz pushed a commit to branch 2.5.x in repository https://gitbox.apache.org/repos/asf/incubator-dubbo.git
The following commit(s) were added to refs/heads/2.5.x by this push: new 1e5b28f Polish alibaba/dubbo#1306 1e5b28f is described below commit 1e5b28f458ee5bb9ea3cb656fc5932e1296b3ee4 Author: mercyblitz <mercybl...@gmail.com> AuthorDate: Fri Mar 30 23:33:37 2018 +0800 Polish alibaba/dubbo#1306 --- .../AnnotationPropertyValuesAdapter.java | 92 ++++++++++++ .../DubboConfigBindingBeanPostProcessor.java | 115 ++++++++++++--- .../ReferenceAnnotationBeanPostProcessor.java | 161 +++++++++++++++++---- .../factory/annotation/ReferenceBeanBuilder.java | 26 +++- .../ServiceAnnotationBeanPostProcessor.java | 49 +++---- .../annotation/DubboConfigBindingRegistrar.java | 64 +++----- .../properties/AbstractDubboConfigBinder.java | 69 +++++++++ .../properties/DefaultDubboConfigBinder.java | 46 ++++++ .../context/properties/DubboConfigBinder.java | 58 ++++++++ .../converter/StringArrayToMapConverter.java} | 75 +++++----- .../converter/StringArrayToStringConverter.java} | 74 +++++----- .../dubbo/config/spring/util/AnnotationUtils.java | 89 ++++++++++++ .../dubbo/config/spring/util/ObjectUtils.java} | 74 +++++----- .../config/spring/util/PropertySourcesUtils.java | 18 ++- .../annotation/provider/AnnotationServiceImpl.java | 2 +- .../AnnotationPropertyValuesAdapterTest.java | 158 ++++++++++++++++++++ .../DubboConfigBindingBeanPostProcessorTest.java | 66 +++++++++ .../ReferenceAnnotationBeanPostProcessorTest.java | 95 ++++++++++-- .../ServiceAnnotationBeanPostProcessorTest.java | 3 +- .../properties/DefaultDubboConfigBinderTest.java | 56 +++++++ .../converter/StringArrayToMapConverterTest.java} | 89 +++++++----- .../StringArrayToStringConverterTest.java} | 83 ++++++----- 22 files changed, 1241 insertions(+), 321 deletions(-) diff --git a/dubbo-config/dubbo-config-spring/src/main/java/com/alibaba/dubbo/config/spring/beans/factory/annotation/AnnotationPropertyValuesAdapter.java b/dubbo-config/dubbo-config-spring/src/main/java/com/alibaba/dubbo/config/spring/beans/factory/annotation/AnnotationPropertyValuesAdapter.java new file mode 100644 index 0000000..751399f --- /dev/null +++ b/dubbo-config/dubbo-config-spring/src/main/java/com/alibaba/dubbo/config/spring/beans/factory/annotation/AnnotationPropertyValuesAdapter.java @@ -0,0 +1,92 @@ +/* + * 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 com.alibaba.dubbo.config.spring.beans.factory.annotation; + +import org.springframework.beans.MutablePropertyValues; +import org.springframework.beans.PropertyValue; +import org.springframework.beans.PropertyValues; +import org.springframework.core.env.PropertyResolver; + +import java.lang.annotation.Annotation; + +import static com.alibaba.dubbo.config.spring.util.AnnotationUtils.getAttributes; + +/** + * {@link Annotation} {@link PropertyValues} Adapter + * + * @see Annotation + * @see PropertyValues + * @since 2.5.11 + */ +class AnnotationPropertyValuesAdapter implements PropertyValues { + + private final Annotation annotation; + + private final PropertyResolver propertyResolver; + + private final boolean ignoreDefaultValue; + + private final PropertyValues delegate; + + public AnnotationPropertyValuesAdapter(Annotation annotation, PropertyResolver propertyResolver, boolean ignoreDefaultValue, String... ignoreAttributeNames) { + this.annotation = annotation; + this.propertyResolver = propertyResolver; + this.ignoreDefaultValue = ignoreDefaultValue; + this.delegate = adapt(annotation, ignoreDefaultValue, ignoreAttributeNames); + } + + public AnnotationPropertyValuesAdapter(Annotation annotation, PropertyResolver propertyResolver, String... ignoreAttributeNames) { + this(annotation, propertyResolver, true, ignoreAttributeNames); + } + + private PropertyValues adapt(Annotation annotation, boolean ignoreDefaultValue, String... ignoreAttributeNames) { + return new MutablePropertyValues(getAttributes(annotation, propertyResolver, ignoreDefaultValue, ignoreAttributeNames)); + } + + public Annotation getAnnotation() { + return annotation; + } + + public boolean isIgnoreDefaultValue() { + return ignoreDefaultValue; + } + + @Override + public PropertyValue[] getPropertyValues() { + return delegate.getPropertyValues(); + } + + @Override + public PropertyValue getPropertyValue(String propertyName) { + return delegate.getPropertyValue(propertyName); + } + + @Override + public PropertyValues changesSince(PropertyValues old) { + return delegate.changesSince(old); + } + + @Override + public boolean contains(String propertyName) { + return delegate.contains(propertyName); + } + + @Override + public boolean isEmpty() { + return delegate.isEmpty(); + } +} diff --git a/dubbo-config/dubbo-config-spring/src/main/java/com/alibaba/dubbo/config/spring/beans/factory/annotation/DubboConfigBindingBeanPostProcessor.java b/dubbo-config/dubbo-config-spring/src/main/java/com/alibaba/dubbo/config/spring/beans/factory/annotation/DubboConfigBindingBeanPostProcessor.java index 6899ad4..6248ed3 100644 --- a/dubbo-config/dubbo-config-spring/src/main/java/com/alibaba/dubbo/config/spring/beans/factory/annotation/DubboConfigBindingBeanPostProcessor.java +++ b/dubbo-config/dubbo-config-spring/src/main/java/com/alibaba/dubbo/config/spring/beans/factory/annotation/DubboConfigBindingBeanPostProcessor.java @@ -17,13 +17,25 @@ package com.alibaba.dubbo.config.spring.beans.factory.annotation; import com.alibaba.dubbo.common.utils.Assert; +import com.alibaba.dubbo.config.AbstractConfig; import com.alibaba.dubbo.config.spring.context.annotation.DubboConfigBindingRegistrar; import com.alibaba.dubbo.config.spring.context.annotation.EnableDubboConfigBinding; +import com.alibaba.dubbo.config.spring.context.properties.DefaultDubboConfigBinder; +import com.alibaba.dubbo.config.spring.context.properties.DubboConfigBinder; +import com.alibaba.dubbo.config.spring.util.BeanFactoryUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.beans.BeansException; import org.springframework.beans.PropertyValues; +import org.springframework.beans.factory.InitializingBean; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.config.BeanFactoryPostProcessor; import org.springframework.beans.factory.config.BeanPostProcessor; +import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; +import org.springframework.context.ApplicationContext; +import org.springframework.context.ApplicationContextAware; +import org.springframework.context.EnvironmentAware; +import org.springframework.core.env.Environment; import org.springframework.validation.DataBinder; import java.util.Arrays; @@ -35,43 +47,52 @@ import java.util.Arrays; * @see DubboConfigBindingRegistrar * @since 2.5.8 */ -public class DubboConfigBindingBeanPostProcessor implements BeanPostProcessor { + +public class DubboConfigBindingBeanPostProcessor implements BeanPostProcessor, ApplicationContextAware, InitializingBean { private final Log log = LogFactory.getLog(getClass()); /** - * Binding Bean Name + * The prefix of Configuration Properties */ - private final String beanName; + private final String prefix; /** - * Binding {@link PropertyValues} + * Binding Bean Name */ - private final PropertyValues propertyValues; + private final String beanName; + private DubboConfigBinder dubboConfigBinder; + + private ApplicationContext applicationContext; + + private boolean ignoreUnknownFields = true; + + private boolean ignoreInvalidFields = true; /** - * @param beanName Binding Bean Name - * @param propertyValues {@link PropertyValues} + * @param prefix the prefix of Configuration Properties + * @param beanName the binding Bean Name */ - public DubboConfigBindingBeanPostProcessor(String beanName, PropertyValues propertyValues) { + public DubboConfigBindingBeanPostProcessor(String prefix, String beanName) { + Assert.notNull(prefix, "The prefix of Configuration Properties must not be null"); Assert.notNull(beanName, "The name of bean must not be null"); - Assert.notNull(propertyValues, "The PropertyValues of bean must not be null"); + this.prefix = prefix; this.beanName = beanName; - this.propertyValues = propertyValues; } @Override public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { - if (beanName.equals(this.beanName)) { - DataBinder dataBinder = new DataBinder(bean); - // TODO ignore invalid fields by annotation attribute - dataBinder.setIgnoreInvalidFields(true); - dataBinder.bind(propertyValues); + if (beanName.equals(this.beanName) && bean instanceof AbstractConfig) { + + AbstractConfig dubboConfig = (AbstractConfig) bean; + + dubboConfigBinder.bind(prefix, dubboConfig); + if (log.isInfoEnabled()) { - log.info("The properties of bean [name : " + beanName + "] have been binding by values : " - + Arrays.asList(propertyValues.getPropertyValues())); + log.info("The properties of bean [name : " + beanName + "] have been binding by prefix of " + + "configuration properties : " + prefix); } } @@ -79,10 +100,70 @@ public class DubboConfigBindingBeanPostProcessor implements BeanPostProcessor { } + public boolean isIgnoreUnknownFields() { + return ignoreUnknownFields; + } + + public void setIgnoreUnknownFields(boolean ignoreUnknownFields) { + this.ignoreUnknownFields = ignoreUnknownFields; + } + + public boolean isIgnoreInvalidFields() { + return ignoreInvalidFields; + } + + public void setIgnoreInvalidFields(boolean ignoreInvalidFields) { + this.ignoreInvalidFields = ignoreInvalidFields; + } + + public DubboConfigBinder getDubboConfigBinder() { + return dubboConfigBinder; + } + + public void setDubboConfigBinder(DubboConfigBinder dubboConfigBinder) { + this.dubboConfigBinder = dubboConfigBinder; + } @Override public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { return bean; } + @Override + public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { + this.applicationContext = applicationContext; + } + + @Override + public void afterPropertiesSet() throws Exception { + + if (dubboConfigBinder == null) { + try { + dubboConfigBinder = applicationContext.getBean(DubboConfigBinder.class); + } catch (BeansException ignored) { + if (log.isDebugEnabled()) { + log.debug("DubboConfigBinder Bean can't be found in ApplicationContext."); + } + // Use Default implementation + dubboConfigBinder = createDubboConfigBinder(applicationContext.getEnvironment()); + } + } + + dubboConfigBinder.setIgnoreUnknownFields(ignoreUnknownFields); + dubboConfigBinder.setIgnoreInvalidFields(ignoreInvalidFields); + + } + + /** + * Create {@link DubboConfigBinder} instance. + * + * @param environment + * @return {@link DefaultDubboConfigBinder} + */ + protected DubboConfigBinder createDubboConfigBinder(Environment environment) { + DefaultDubboConfigBinder defaultDubboConfigBinder = new DefaultDubboConfigBinder(); + defaultDubboConfigBinder.setEnvironment(environment); + return defaultDubboConfigBinder; + } + } diff --git a/dubbo-config/dubbo-config-spring/src/main/java/com/alibaba/dubbo/config/spring/beans/factory/annotation/ReferenceAnnotationBeanPostProcessor.java b/dubbo-config/dubbo-config-spring/src/main/java/com/alibaba/dubbo/config/spring/beans/factory/annotation/ReferenceAnnotationBeanPostProcessor.java index d8411de..31478f6 100644 --- a/dubbo-config/dubbo-config-spring/src/main/java/com/alibaba/dubbo/config/spring/beans/factory/annotation/ReferenceAnnotationBeanPostProcessor.java +++ b/dubbo-config/dubbo-config-spring/src/main/java/com/alibaba/dubbo/config/spring/beans/factory/annotation/ReferenceAnnotationBeanPostProcessor.java @@ -33,6 +33,7 @@ import org.springframework.beans.factory.support.RootBeanDefinition; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextAware; import org.springframework.core.PriorityOrdered; +import org.springframework.core.env.Environment; import org.springframework.util.ClassUtils; import org.springframework.util.ReflectionUtils; import org.springframework.util.StringUtils; @@ -41,9 +42,7 @@ import java.beans.PropertyDescriptor; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.lang.reflect.Modifier; -import java.util.Collection; -import java.util.LinkedList; -import java.util.List; +import java.util.*; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; @@ -73,8 +72,8 @@ public class ReferenceAnnotationBeanPostProcessor extends InstantiationAwareBean private ClassLoader classLoader; - private final ConcurrentMap<String, InjectionMetadata> injectionMetadataCache = - new ConcurrentHashMap<String, InjectionMetadata>(256); + private final ConcurrentMap<String, ReferenceInjectionMetadata> injectionMetadataCache = + new ConcurrentHashMap<String, ReferenceInjectionMetadata>(256); private final ConcurrentMap<String, ReferenceBean<?>> referenceBeansCache = new ConcurrentHashMap<String, ReferenceBean<?>>(); @@ -101,9 +100,9 @@ public class ReferenceAnnotationBeanPostProcessor extends InstantiationAwareBean * @param beanClass The {@link Class} of Bean * @return non-null {@link List} */ - private List<InjectionMetadata.InjectedElement> findFieldReferenceMetadata(final Class<?> beanClass) { + private List<ReferenceFieldElement> findFieldReferenceMetadata(final Class<?> beanClass) { - final List<InjectionMetadata.InjectedElement> elements = new LinkedList<InjectionMetadata.InjectedElement>(); + final List<ReferenceFieldElement> elements = new LinkedList<ReferenceFieldElement>(); ReflectionUtils.doWithFields(beanClass, new ReflectionUtils.FieldCallback() { @Override @@ -136,9 +135,9 @@ public class ReferenceAnnotationBeanPostProcessor extends InstantiationAwareBean * @param beanClass The {@link Class} of Bean * @return non-null {@link List} */ - private List<InjectionMetadata.InjectedElement> findMethodReferenceMetadata(final Class<?> beanClass) { + private List<ReferenceMethodElement> findMethodReferenceMetadata(final Class<?> beanClass) { - final List<InjectionMetadata.InjectedElement> elements = new LinkedList<InjectionMetadata.InjectedElement>(); + final List<ReferenceMethodElement> elements = new LinkedList<ReferenceMethodElement>(); ReflectionUtils.doWithMethods(beanClass, new ReflectionUtils.MethodCallback() { @Override @@ -180,15 +179,10 @@ public class ReferenceAnnotationBeanPostProcessor extends InstantiationAwareBean * @param beanClass * @return */ - private InjectionMetadata buildReferenceMetadata(final Class<?> beanClass) { - - final List<InjectionMetadata.InjectedElement> elements = new LinkedList<InjectionMetadata.InjectedElement>(); - - elements.addAll(findFieldReferenceMetadata(beanClass)); - - elements.addAll(findMethodReferenceMetadata(beanClass)); - - return new InjectionMetadata(beanClass, elements); + private ReferenceInjectionMetadata buildReferenceMetadata(final Class<?> beanClass) { + Collection<ReferenceFieldElement> fieldElements = findFieldReferenceMetadata(beanClass); + Collection<ReferenceMethodElement> methodElements = findMethodReferenceMetadata(beanClass); + return new ReferenceInjectionMetadata(beanClass, fieldElements, methodElements); } @@ -196,7 +190,7 @@ public class ReferenceAnnotationBeanPostProcessor extends InstantiationAwareBean // Fall back to class name as cache key, for backwards compatibility with custom callers. String cacheKey = (StringUtils.hasLength(beanName) ? beanName : clazz.getName()); // Quick check on the concurrent map first, with minimal locking. - InjectionMetadata metadata = this.injectionMetadataCache.get(cacheKey); + ReferenceInjectionMetadata metadata = this.injectionMetadataCache.get(cacheKey); if (InjectionMetadata.needsRefresh(metadata, clazz)) { synchronized (this.injectionMetadataCache) { metadata = this.injectionMetadataCache.get(cacheKey); @@ -270,6 +264,43 @@ public class ReferenceAnnotationBeanPostProcessor extends InstantiationAwareBean return this.referenceBeansCache.values(); } + + /** + * {@link Reference} {@link InjectionMetadata} implementation + * + * @since 2.5.11 + */ + private static class ReferenceInjectionMetadata extends InjectionMetadata { + + private final Collection<ReferenceFieldElement> fieldElements; + + private final Collection<ReferenceMethodElement> methodElements; + + + public ReferenceInjectionMetadata(Class<?> targetClass, Collection<ReferenceFieldElement> fieldElements, + Collection<ReferenceMethodElement> methodElements) { + super(targetClass, combine(fieldElements, methodElements)); + this.fieldElements = fieldElements; + this.methodElements = methodElements; + } + + private static <T> Collection<T> combine(Collection<? extends T>... elements) { + List<T> allElements = new ArrayList<T>(); + for (Collection<? extends T> e : elements) { + allElements.addAll(e); + } + return allElements; + } + + public Collection<ReferenceFieldElement> getFieldElements() { + return fieldElements; + } + + public Collection<ReferenceMethodElement> getMethodElements() { + return methodElements; + } + } + /** * {@link Reference} {@link Method} {@link InjectionMetadata.InjectedElement} */ @@ -279,6 +310,8 @@ public class ReferenceAnnotationBeanPostProcessor extends InstantiationAwareBean private final Reference reference; + private volatile ReferenceBean<?> referenceBean; + protected ReferenceMethodElement(Method method, PropertyDescriptor pd, Reference reference) { super(method, pd); this.method = method; @@ -290,11 +323,11 @@ public class ReferenceAnnotationBeanPostProcessor extends InstantiationAwareBean Class<?> referenceClass = pd.getPropertyType(); - Object referenceBean = buildReferenceBean(reference, referenceClass); + referenceBean = buildReferenceBean(reference, referenceClass); ReflectionUtils.makeAccessible(method); - method.invoke(bean, referenceBean); + method.invoke(bean, referenceBean.getObject()); } @@ -309,6 +342,8 @@ public class ReferenceAnnotationBeanPostProcessor extends InstantiationAwareBean private final Reference reference; + private volatile ReferenceBean<?> referenceBean; + protected ReferenceFieldElement(Field field, Reference reference) { super(field, null); this.field = field; @@ -320,17 +355,17 @@ public class ReferenceAnnotationBeanPostProcessor extends InstantiationAwareBean Class<?> referenceClass = field.getType(); - Object referenceBean = buildReferenceBean(reference, referenceClass); + referenceBean = buildReferenceBean(reference, referenceClass); ReflectionUtils.makeAccessible(field); - field.set(bean, referenceBean); + field.set(bean, referenceBean.getObject()); } } - private Object buildReferenceBean(Reference reference, Class<?> referenceClass) throws Exception { + private ReferenceBean<?> buildReferenceBean(Reference reference, Class<?> referenceClass) throws Exception { String referenceBeanCacheKey = generateReferenceBeanCacheKey(reference, referenceClass); @@ -348,8 +383,8 @@ public class ReferenceAnnotationBeanPostProcessor extends InstantiationAwareBean } + return referenceBean; - return referenceBean.get(); } @@ -360,11 +395,17 @@ public class ReferenceAnnotationBeanPostProcessor extends InstantiationAwareBean * @param beanClass {@link Class} * @return */ - private static String generateReferenceBeanCacheKey(Reference reference, Class<?> beanClass) { + private String generateReferenceBeanCacheKey(Reference reference, Class<?> beanClass) { String interfaceName = resolveInterfaceName(reference, beanClass); - String key = reference.group() + "/" + interfaceName + ":" + reference.version(); + String key = reference.url() + "/" + interfaceName + + "/" + reference.version() + + "/" + reference.group(); + + Environment environment = applicationContext.getEnvironment(); + + key = environment.resolvePlaceholders(key); return key; @@ -390,4 +431,70 @@ public class ReferenceAnnotationBeanPostProcessor extends InstantiationAwareBean } + + /** + * Get {@link ReferenceBean} {@link Map} in injected field. + * + * @return non-null {@link Map} + * @since 2.5.11 + */ + public Map<InjectionMetadata.InjectedElement, ReferenceBean<?>> getInjectedFieldReferenceBeanMap() { + + Map<InjectionMetadata.InjectedElement, ReferenceBean<?>> injectedElementReferenceBeanMap = + new LinkedHashMap<InjectionMetadata.InjectedElement, ReferenceBean<?>>(); + + for (ReferenceInjectionMetadata metadata : injectionMetadataCache.values()) { + + Collection<ReferenceFieldElement> fieldElements = metadata.getFieldElements(); + + for (ReferenceFieldElement fieldElement : fieldElements) { + + injectedElementReferenceBeanMap.put(fieldElement, fieldElement.referenceBean); + + } + + } + + return injectedElementReferenceBeanMap; + + } + + /** + * Get {@link ReferenceBean} {@link Map} in injected method. + * + * @return non-null {@link Map} + * @since 2.5.11 + */ + public Map<InjectionMetadata.InjectedElement, ReferenceBean<?>> getInjectedMethodReferenceBeanMap() { + + Map<InjectionMetadata.InjectedElement, ReferenceBean<?>> injectedElementReferenceBeanMap = + new LinkedHashMap<InjectionMetadata.InjectedElement, ReferenceBean<?>>(); + + for (ReferenceInjectionMetadata metadata : injectionMetadataCache.values()) { + + Collection<ReferenceMethodElement> methodElements = metadata.getMethodElements(); + + for (ReferenceMethodElement methodElement : methodElements) { + + injectedElementReferenceBeanMap.put(methodElement, methodElement.referenceBean); + + } + + } + + return injectedElementReferenceBeanMap; + + } + + private <T> T getFieldValue(Object object, String fieldName, Class<T> fieldType) { + + Field field = ReflectionUtils.findField(object.getClass(), fieldName, fieldType); + + ReflectionUtils.makeAccessible(field); + + return (T) ReflectionUtils.getField(field, object); + + } + + } diff --git a/dubbo-config/dubbo-config-spring/src/main/java/com/alibaba/dubbo/config/spring/beans/factory/annotation/ReferenceBeanBuilder.java b/dubbo-config/dubbo-config-spring/src/main/java/com/alibaba/dubbo/config/spring/beans/factory/annotation/ReferenceBeanBuilder.java index d2cc56d..5d9418f 100644 --- a/dubbo-config/dubbo-config-spring/src/main/java/com/alibaba/dubbo/config/spring/beans/factory/annotation/ReferenceBeanBuilder.java +++ b/dubbo-config/dubbo-config-spring/src/main/java/com/alibaba/dubbo/config/spring/beans/factory/annotation/ReferenceBeanBuilder.java @@ -19,12 +19,18 @@ package com.alibaba.dubbo.config.spring.beans.factory.annotation; import com.alibaba.dubbo.config.ConsumerConfig; import com.alibaba.dubbo.config.annotation.Reference; import com.alibaba.dubbo.config.spring.ReferenceBean; +import com.alibaba.dubbo.config.spring.convert.converter.StringArrayToMapConverter; +import com.alibaba.dubbo.config.spring.convert.converter.StringArrayToStringConverter; import org.springframework.context.ApplicationContext; +import org.springframework.core.convert.ConversionService; +import org.springframework.core.convert.support.DefaultConversionService; import org.springframework.util.Assert; import org.springframework.util.ClassUtils; import org.springframework.util.StringUtils; +import org.springframework.validation.DataBinder; import static com.alibaba.dubbo.config.spring.util.BeanFactoryUtils.getOptionalBean; +import static com.alibaba.dubbo.config.spring.util.ObjectUtils.of; /** * {@link ReferenceBean} Builder @@ -80,14 +86,30 @@ class ReferenceBeanBuilder extends AbstractAnnotationConfigBeanBuilder<Reference @Override protected ReferenceBean doBuild() { - return new ReferenceBean<Object>(annotation); + return new ReferenceBean<Object>(); } @Override - protected void preConfigureBean(Reference annotation, ReferenceBean bean) { + protected void preConfigureBean(Reference reference, ReferenceBean referenceBean) { Assert.notNull(interfaceClass, "The interface class must set first!"); + DataBinder dataBinder = new DataBinder(referenceBean); + // Set ConversionService + dataBinder.setConversionService(getConversionService()); + // Ignore those fields + String[] ignoreAttributeNames = of("application", "module", "consumer", "monitor", "registry"); +// dataBinder.setDisallowedFields(ignoreAttributeNames); + // Bind annotation attributes + dataBinder.bind(new AnnotationPropertyValuesAdapter(reference, applicationContext.getEnvironment(), ignoreAttributeNames)); } + private ConversionService getConversionService() { + DefaultConversionService conversionService = new DefaultConversionService(); + conversionService.addConverter(new StringArrayToStringConverter()); + conversionService.addConverter(new StringArrayToMapConverter()); + return conversionService; + } + + @Override protected String resolveModuleConfigBeanName(Reference annotation) { return annotation.module(); diff --git a/dubbo-config/dubbo-config-spring/src/main/java/com/alibaba/dubbo/config/spring/beans/factory/annotation/ServiceAnnotationBeanPostProcessor.java b/dubbo-config/dubbo-config-spring/src/main/java/com/alibaba/dubbo/config/spring/beans/factory/annotation/ServiceAnnotationBeanPostProcessor.java index 1d27345..207b3f7 100644 --- a/dubbo-config/dubbo-config-spring/src/main/java/com/alibaba/dubbo/config/spring/beans/factory/annotation/ServiceAnnotationBeanPostProcessor.java +++ b/dubbo-config/dubbo-config-spring/src/main/java/com/alibaba/dubbo/config/spring/beans/factory/annotation/ServiceAnnotationBeanPostProcessor.java @@ -21,20 +21,11 @@ import com.alibaba.dubbo.common.logger.LoggerFactory; import com.alibaba.dubbo.config.annotation.Service; import com.alibaba.dubbo.config.spring.ServiceBean; import com.alibaba.dubbo.config.spring.context.annotation.DubboClassPathBeanDefinitionScanner; - import org.springframework.beans.BeansException; +import org.springframework.beans.MutablePropertyValues; import org.springframework.beans.factory.BeanClassLoaderAware; -import org.springframework.beans.factory.config.BeanDefinition; -import org.springframework.beans.factory.config.BeanDefinitionHolder; -import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; -import org.springframework.beans.factory.config.RuntimeBeanReference; -import org.springframework.beans.factory.config.SingletonBeanRegistry; -import org.springframework.beans.factory.support.AbstractBeanDefinition; -import org.springframework.beans.factory.support.BeanDefinitionBuilder; -import org.springframework.beans.factory.support.BeanDefinitionRegistry; -import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor; -import org.springframework.beans.factory.support.BeanNameGenerator; -import org.springframework.beans.factory.support.ManagedList; +import org.springframework.beans.factory.config.*; +import org.springframework.beans.factory.support.*; import org.springframework.context.EnvironmentAware; import org.springframework.context.ResourceLoaderAware; import org.springframework.context.annotation.AnnotationBeanNameGenerator; @@ -44,18 +35,11 @@ import org.springframework.context.annotation.ConfigurationClassPostProcessor; import org.springframework.core.env.Environment; import org.springframework.core.io.ResourceLoader; import org.springframework.core.type.filter.AnnotationTypeFilter; -import org.springframework.util.Assert; -import org.springframework.util.ClassUtils; -import org.springframework.util.CollectionUtils; -import org.springframework.util.ObjectUtils; -import org.springframework.util.StringUtils; - -import java.util.Arrays; -import java.util.Collection; -import java.util.LinkedHashSet; -import java.util.List; -import java.util.Set; +import org.springframework.util.*; + +import java.util.*; +import static com.alibaba.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; import static org.springframework.core.annotation.AnnotationUtils.findAnnotation; @@ -356,11 +340,20 @@ public class ServiceAnnotationBeanPostProcessor implements BeanDefinitionRegistr private AbstractBeanDefinition buildServiceBeanDefinition(Service service, Class<?> interfaceClass, String annotatedServiceBeanName) { - BeanDefinitionBuilder builder = rootBeanDefinition(ServiceBean.class) - .addConstructorArgValue(service) - // References "ref" property to annotated-@Service Bean - .addPropertyReference("ref", annotatedServiceBeanName) - .addPropertyValue("interface", interfaceClass.getName()); + BeanDefinitionBuilder builder = rootBeanDefinition(ServiceBean.class); + + AbstractBeanDefinition beanDefinition = builder.getBeanDefinition(); + + MutablePropertyValues propertyValues = beanDefinition.getPropertyValues(); + + String[] ignoreAttributeNames = of("provider", "monitor", "application", "module", "registry", "protocol", "interface"); + + propertyValues.addPropertyValues(new AnnotationPropertyValuesAdapter(service, environment, ignoreAttributeNames)); + + // References "ref" property to annotated-@Service Bean + addPropertyReference(builder, "ref", annotatedServiceBeanName); + // Set interface + builder.addPropertyValue("interface", interfaceClass.getName()); /** * Add {@link com.alibaba.dubbo.config.ProviderConfig} Bean reference diff --git a/dubbo-config/dubbo-config-spring/src/main/java/com/alibaba/dubbo/config/spring/context/annotation/DubboConfigBindingRegistrar.java b/dubbo-config/dubbo-config-spring/src/main/java/com/alibaba/dubbo/config/spring/context/annotation/DubboConfigBindingRegistrar.java index cd9cadd..452d9d3 100644 --- a/dubbo-config/dubbo-config-spring/src/main/java/com/alibaba/dubbo/config/spring/context/annotation/DubboConfigBindingRegistrar.java +++ b/dubbo-config/dubbo-config-spring/src/main/java/com/alibaba/dubbo/config/spring/context/annotation/DubboConfigBindingRegistrar.java @@ -20,8 +20,6 @@ import com.alibaba.dubbo.config.AbstractConfig; import com.alibaba.dubbo.config.spring.beans.factory.annotation.DubboConfigBindingBeanPostProcessor; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; -import org.springframework.beans.MutablePropertyValues; -import org.springframework.beans.PropertyValues; import org.springframework.beans.factory.config.BeanDefinition; import org.springframework.beans.factory.support.AbstractBeanDefinition; import org.springframework.beans.factory.support.BeanDefinitionBuilder; @@ -30,15 +28,21 @@ import org.springframework.beans.factory.support.BeanDefinitionRegistry; import org.springframework.context.EnvironmentAware; import org.springframework.context.annotation.ImportBeanDefinitionRegistrar; import org.springframework.core.annotation.AnnotationAttributes; -import org.springframework.core.env.*; +import org.springframework.core.env.ConfigurableEnvironment; +import org.springframework.core.env.Environment; +import org.springframework.core.env.PropertySources; import org.springframework.core.type.AnnotationMetadata; import org.springframework.util.Assert; import org.springframework.util.CollectionUtils; import org.springframework.util.StringUtils; -import java.util.*; +import java.util.Collections; +import java.util.LinkedHashSet; +import java.util.Map; +import java.util.Set; import static com.alibaba.dubbo.config.spring.util.PropertySourcesUtils.getSubProperties; +import static com.alibaba.dubbo.config.spring.util.PropertySourcesUtils.normalizePrefix; import static org.springframework.beans.factory.support.BeanDefinitionBuilder.rootBeanDefinition; import static org.springframework.beans.factory.support.BeanDefinitionReaderUtils.registerWithGeneratedName; @@ -82,9 +86,7 @@ public class DubboConfigBindingRegistrar implements ImportBeanDefinitionRegistra boolean multiple, BeanDefinitionRegistry registry) { - PropertySources propertySources = environment.getPropertySources(); - - Map<String, String> properties = getSubProperties(propertySources, prefix); + Map<String, String> properties = getSubProperties(environment.getPropertySources(), prefix); if (CollectionUtils.isEmpty(properties)) { if (log.isDebugEnabled()) { @@ -94,16 +96,14 @@ public class DubboConfigBindingRegistrar implements ImportBeanDefinitionRegistra return; } - Set<String> beanNames = multiple ? resolveMultipleBeanNames(prefix, properties) : - Collections.singleton(resolveSingleBeanName(configClass, properties, registry)); + Set<String> beanNames = multiple ? resolveMultipleBeanNames(properties) : + Collections.singleton(resolveSingleBeanName(properties, configClass, registry)); for (String beanName : beanNames) { registerDubboConfigBean(beanName, configClass, registry); - MutablePropertyValues propertyValues = resolveBeanPropertyValues(beanName, multiple, properties); - - registerDubboConfigBindingBeanPostProcessor(beanName, propertyValues, registry); + registerDubboConfigBindingBeanPostProcessor(prefix, beanName, multiple, registry); } @@ -125,14 +125,16 @@ public class DubboConfigBindingRegistrar implements ImportBeanDefinitionRegistra } - private void registerDubboConfigBindingBeanPostProcessor(String beanName, PropertyValues propertyValues, + private void registerDubboConfigBindingBeanPostProcessor(String prefix, String beanName, boolean multiple, BeanDefinitionRegistry registry) { Class<?> processorClass = DubboConfigBindingBeanPostProcessor.class; BeanDefinitionBuilder builder = rootBeanDefinition(processorClass); - builder.addConstructorArgValue(beanName).addConstructorArgValue(propertyValues); + String actualPrefix = multiple ? normalizePrefix(prefix) + beanName : prefix; + + builder.addConstructorArgValue(actualPrefix).addConstructorArgValue(beanName); AbstractBeanDefinition beanDefinition = builder.getBeanDefinition(); @@ -147,36 +149,6 @@ public class DubboConfigBindingRegistrar implements ImportBeanDefinitionRegistra } - private MutablePropertyValues resolveBeanPropertyValues(String beanName, boolean multiple, - Map<String, String> properties) { - - MutablePropertyValues propertyValues = new MutablePropertyValues(); - - if (multiple) { // For Multiple Beans - - MutablePropertySources propertySources = new MutablePropertySources(); - propertySources.addFirst(new MapPropertySource(beanName, new TreeMap<String, Object>(properties))); - - Map<String, String> subProperties = getSubProperties(propertySources, beanName); - - propertyValues.addPropertyValues(subProperties); - - - } else { // For Single Bean - - for (Map.Entry<String, String> entry : properties.entrySet()) { - String propertyName = entry.getKey(); - if (!propertyName.contains(".")) { // ignore property name with "." - propertyValues.addPropertyValue(propertyName, entry.getValue()); - } - } - - } - - return propertyValues; - - } - @Override public void setEnvironment(Environment environment) { @@ -186,7 +158,7 @@ public class DubboConfigBindingRegistrar implements ImportBeanDefinitionRegistra } - private Set<String> resolveMultipleBeanNames(String prefix, Map<String, String> properties) { + private Set<String> resolveMultipleBeanNames(Map<String, String> properties) { Set<String> beanNames = new LinkedHashSet<String>(); @@ -207,7 +179,7 @@ public class DubboConfigBindingRegistrar implements ImportBeanDefinitionRegistra } - private String resolveSingleBeanName(Class<? extends AbstractConfig> configClass, Map<String, String> properties, + private String resolveSingleBeanName(Map<String, String> properties, Class<? extends AbstractConfig> configClass, BeanDefinitionRegistry registry) { String beanName = properties.get("id"); diff --git a/dubbo-config/dubbo-config-spring/src/main/java/com/alibaba/dubbo/config/spring/context/properties/AbstractDubboConfigBinder.java b/dubbo-config/dubbo-config-spring/src/main/java/com/alibaba/dubbo/config/spring/context/properties/AbstractDubboConfigBinder.java new file mode 100644 index 0000000..b103367 --- /dev/null +++ b/dubbo-config/dubbo-config-spring/src/main/java/com/alibaba/dubbo/config/spring/context/properties/AbstractDubboConfigBinder.java @@ -0,0 +1,69 @@ +/* + * 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 com.alibaba.dubbo.config.spring.context.properties; + +import org.springframework.core.env.ConfigurableEnvironment; +import org.springframework.core.env.Environment; +import org.springframework.core.env.PropertySource; + +/** + * Abstract {@link DubboConfigBinder} implementation + */ +public abstract class AbstractDubboConfigBinder implements DubboConfigBinder { + + private Iterable<PropertySource<?>> propertySources; + + private boolean ignoreUnknownFields = true; + + private boolean ignoreInvalidFields = false; + + /** + * Get multiple {@link PropertySource propertySources} + * + * @return multiple {@link PropertySource propertySources} + */ + protected Iterable<PropertySource<?>> getPropertySources() { + return propertySources; + } + + public boolean isIgnoreUnknownFields() { + return ignoreUnknownFields; + } + + @Override + public void setIgnoreUnknownFields(boolean ignoreUnknownFields) { + this.ignoreUnknownFields = ignoreUnknownFields; + } + + public boolean isIgnoreInvalidFields() { + return ignoreInvalidFields; + } + + @Override + public void setIgnoreInvalidFields(boolean ignoreInvalidFields) { + this.ignoreInvalidFields = ignoreInvalidFields; + } + + @Override + public final void setEnvironment(Environment environment) { + + if (environment instanceof ConfigurableEnvironment) { + this.propertySources = ((ConfigurableEnvironment) environment).getPropertySources(); + } + + } +} diff --git a/dubbo-config/dubbo-config-spring/src/main/java/com/alibaba/dubbo/config/spring/context/properties/DefaultDubboConfigBinder.java b/dubbo-config/dubbo-config-spring/src/main/java/com/alibaba/dubbo/config/spring/context/properties/DefaultDubboConfigBinder.java new file mode 100644 index 0000000..52cc87c --- /dev/null +++ b/dubbo-config/dubbo-config-spring/src/main/java/com/alibaba/dubbo/config/spring/context/properties/DefaultDubboConfigBinder.java @@ -0,0 +1,46 @@ +/* + * 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 com.alibaba.dubbo.config.spring.context.properties; + +import com.alibaba.dubbo.config.AbstractConfig; +import org.springframework.beans.MutablePropertyValues; +import org.springframework.validation.DataBinder; + +import java.util.Map; + +import static com.alibaba.dubbo.config.spring.util.PropertySourcesUtils.getSubProperties; + +/** + * Default {@link DubboConfigBinder} implementation based on Spring {@link DataBinder} + */ +public class DefaultDubboConfigBinder extends AbstractDubboConfigBinder { + + @Override + public <C extends AbstractConfig> void bind(String prefix, C dubboConfig) { + DataBinder dataBinder = new DataBinder(dubboConfig); + // Set ignored* + dataBinder.setIgnoreInvalidFields(isIgnoreInvalidFields()); + dataBinder.setIgnoreUnknownFields(isIgnoreUnknownFields()); + // Get properties under specified prefix from PropertySources + Map<String, String> properties = getSubProperties(getPropertySources(), prefix); + // Convert Map to MutablePropertyValues + MutablePropertyValues propertyValues = new MutablePropertyValues(properties); + // Bind + dataBinder.bind(propertyValues); + } + +} diff --git a/dubbo-config/dubbo-config-spring/src/main/java/com/alibaba/dubbo/config/spring/context/properties/DubboConfigBinder.java b/dubbo-config/dubbo-config-spring/src/main/java/com/alibaba/dubbo/config/spring/context/properties/DubboConfigBinder.java new file mode 100644 index 0000000..c19fadc --- /dev/null +++ b/dubbo-config/dubbo-config-spring/src/main/java/com/alibaba/dubbo/config/spring/context/properties/DubboConfigBinder.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 com.alibaba.dubbo.config.spring.context.properties; + +import com.alibaba.dubbo.config.AbstractConfig; +import org.springframework.context.EnvironmentAware; + +/** + * {@link AbstractConfig DubboConfig} Binder + * + * @see AbstractConfig + * @see EnvironmentAware + * @since 2.5.11 + */ +public interface DubboConfigBinder extends EnvironmentAware { + + /** + * Set whether to ignore unknown fields, that is, whether to ignore bind + * parameters that do not have corresponding fields in the target object. + * <p>Default is "true". Turn this off to enforce that all bind parameters + * must have a matching field in the target object. + * + * @see #bind + */ + void setIgnoreUnknownFields(boolean ignoreUnknownFields); + + /** + * Set whether to ignore invalid fields, that is, whether to ignore bind + * parameters that have corresponding fields in the target object which are + * not accessible (for example because of null values in the nested path). + * <p>Default is "false". + * + * @see #bind + */ + void setIgnoreInvalidFields(boolean ignoreInvalidFields); + + /** + * Bind the properties to {@link C Dubbo Config} Object under specified prefix. + * + * @param prefix + * @param dubboConfig + */ + <C extends AbstractConfig> void bind(String prefix, C dubboConfig); +} diff --git a/dubbo-config/dubbo-config-spring/src/test/java/com/alibaba/dubbo/config/spring/annotation/provider/AnnotationServiceImpl.java b/dubbo-config/dubbo-config-spring/src/main/java/com/alibaba/dubbo/config/spring/convert/converter/StringArrayToMapConverter.java similarity index 57% copy from dubbo-config/dubbo-config-spring/src/test/java/com/alibaba/dubbo/config/spring/annotation/provider/AnnotationServiceImpl.java copy to dubbo-config/dubbo-config-spring/src/main/java/com/alibaba/dubbo/config/spring/convert/converter/StringArrayToMapConverter.java index 7766a1a..56c6d4c 100644 --- a/dubbo-config/dubbo-config-spring/src/test/java/com/alibaba/dubbo/config/spring/annotation/provider/AnnotationServiceImpl.java +++ b/dubbo-config/dubbo-config-spring/src/main/java/com/alibaba/dubbo/config/spring/convert/converter/StringArrayToMapConverter.java @@ -1,37 +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 com.alibaba.dubbo.config.spring.annotation.provider; - -import com.alibaba.dubbo.config.annotation.Service; -import com.alibaba.dubbo.config.spring.api.Box; -import com.alibaba.dubbo.config.spring.api.DemoService; - -/** - * DemoServiceImpl - */ -@Service(version = "1.2") -public class AnnotationServiceImpl implements DemoService { - - public String sayName(String name) { - return "annotation:" + name; - } - - public Box getBox() { - return null; - } - -} \ No newline at end of file +/* + * 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 com.alibaba.dubbo.config.spring.convert.converter; + +import com.alibaba.dubbo.common.utils.CollectionUtils; +import org.springframework.core.convert.converter.Converter; +import org.springframework.util.ObjectUtils; + +import java.util.Map; + +/** + * {@link String}[] to {@link Map} {@link Converter} + * + * @see CollectionUtils#toStringMap(String[]) + * @since 2.5.11 + */ +public class StringArrayToMapConverter implements Converter<String[], Map<String, String>> { + + @Override + public Map<String, String> convert(String[] source) { + return ObjectUtils.isEmpty(source) ? null : CollectionUtils.toStringMap(source); + } + +} diff --git a/dubbo-config/dubbo-config-spring/src/test/java/com/alibaba/dubbo/config/spring/annotation/provider/AnnotationServiceImpl.java b/dubbo-config/dubbo-config-spring/src/main/java/com/alibaba/dubbo/config/spring/convert/converter/StringArrayToStringConverter.java similarity index 58% copy from dubbo-config/dubbo-config-spring/src/test/java/com/alibaba/dubbo/config/spring/annotation/provider/AnnotationServiceImpl.java copy to dubbo-config/dubbo-config-spring/src/main/java/com/alibaba/dubbo/config/spring/convert/converter/StringArrayToStringConverter.java index 7766a1a..23e948b 100644 --- a/dubbo-config/dubbo-config-spring/src/test/java/com/alibaba/dubbo/config/spring/annotation/provider/AnnotationServiceImpl.java +++ b/dubbo-config/dubbo-config-spring/src/main/java/com/alibaba/dubbo/config/spring/convert/converter/StringArrayToStringConverter.java @@ -1,37 +1,37 @@ -/* - * 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 com.alibaba.dubbo.config.spring.annotation.provider; - -import com.alibaba.dubbo.config.annotation.Service; -import com.alibaba.dubbo.config.spring.api.Box; -import com.alibaba.dubbo.config.spring.api.DemoService; - -/** - * DemoServiceImpl - */ -@Service(version = "1.2") -public class AnnotationServiceImpl implements DemoService { - - public String sayName(String name) { - return "annotation:" + name; - } - - public Box getBox() { - return null; - } - -} \ No newline at end of file +/* + * 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 com.alibaba.dubbo.config.spring.convert.converter; + +import org.springframework.core.convert.converter.Converter; +import org.springframework.util.ObjectUtils; +import org.springframework.util.StringUtils; + + +/** + * String[] to String {@ConditionalGenericConverter} + * + * @see StringUtils#arrayToCommaDelimitedString(Object[]) + * @since 2.5.11 + */ +public class StringArrayToStringConverter implements Converter<String[], String> { + + @Override + public String convert(String[] source) { + return ObjectUtils.isEmpty(source) ? null : StringUtils.arrayToCommaDelimitedString(source); + } + +} diff --git a/dubbo-config/dubbo-config-spring/src/main/java/com/alibaba/dubbo/config/spring/util/AnnotationUtils.java b/dubbo-config/dubbo-config-spring/src/main/java/com/alibaba/dubbo/config/spring/util/AnnotationUtils.java new file mode 100644 index 0000000..aa15e56 --- /dev/null +++ b/dubbo-config/dubbo-config-spring/src/main/java/com/alibaba/dubbo/config/spring/util/AnnotationUtils.java @@ -0,0 +1,89 @@ +/* + * 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 com.alibaba.dubbo.config.spring.util; + +import org.springframework.core.env.PropertyResolver; + +import java.lang.annotation.Annotation; +import java.util.HashSet; +import java.util.LinkedHashMap; +import java.util.Map; +import java.util.Set; + +import static java.lang.String.valueOf; +import static org.springframework.core.annotation.AnnotationUtils.getAnnotationAttributes; +import static org.springframework.core.annotation.AnnotationUtils.getDefaultValue; +import static org.springframework.util.CollectionUtils.arrayToList; +import static org.springframework.util.ObjectUtils.nullSafeEquals; +import static org.springframework.util.StringUtils.trimAllWhitespace; + +/** + * Annotation Utilities Class + * + * @see org.springframework.core.annotation.AnnotationUtils + * @since 2.5.11 + */ +public class AnnotationUtils { + + /** + * Get {@link Annotation} attributes + * + * @param annotation + * @param propertyResolver + * @param ignoreDefaultValue + * @return non-null + */ + public static Map<String, Object> getAttributes(Annotation annotation, PropertyResolver propertyResolver, + boolean ignoreDefaultValue, String... ignoreAttributeNames) { + + Set<String> ignoreAttributeNamesSet = new HashSet<String>(arrayToList(ignoreAttributeNames)); + + Map<String, Object> attributes = getAnnotationAttributes(annotation); + + Map<String, Object> actualAttributes = new LinkedHashMap<String, Object>(); + + boolean requiredResolve = propertyResolver != null; + + for (Map.Entry<String, Object> entry : attributes.entrySet()) { + + String attributeName = entry.getKey(); + Object attributeValue = entry.getValue(); + + // ignore default attribute value + if (ignoreDefaultValue && nullSafeEquals(attributeValue, getDefaultValue(annotation, attributeName))) { + continue; + } + + // ignore attribute name + if (ignoreAttributeNamesSet.contains(attributeName)) { + continue; + } + + if (requiredResolve && attributeValue instanceof String) { // Resolve Placeholder + String resolvedValue = propertyResolver.resolvePlaceholders(valueOf(attributeValue)); + attributeValue = trimAllWhitespace(resolvedValue); + } + + actualAttributes.put(attributeName, attributeValue); + + } + + return actualAttributes; + + } + +} diff --git a/dubbo-config/dubbo-config-spring/src/test/java/com/alibaba/dubbo/config/spring/annotation/provider/AnnotationServiceImpl.java b/dubbo-config/dubbo-config-spring/src/main/java/com/alibaba/dubbo/config/spring/util/ObjectUtils.java similarity index 62% copy from dubbo-config/dubbo-config-spring/src/test/java/com/alibaba/dubbo/config/spring/annotation/provider/AnnotationServiceImpl.java copy to dubbo-config/dubbo-config-spring/src/main/java/com/alibaba/dubbo/config/spring/util/ObjectUtils.java index 7766a1a..00db1e7 100644 --- a/dubbo-config/dubbo-config-spring/src/test/java/com/alibaba/dubbo/config/spring/annotation/provider/AnnotationServiceImpl.java +++ b/dubbo-config/dubbo-config-spring/src/main/java/com/alibaba/dubbo/config/spring/util/ObjectUtils.java @@ -1,37 +1,37 @@ -/* - * 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 com.alibaba.dubbo.config.spring.annotation.provider; - -import com.alibaba.dubbo.config.annotation.Service; -import com.alibaba.dubbo.config.spring.api.Box; -import com.alibaba.dubbo.config.spring.api.DemoService; - -/** - * DemoServiceImpl - */ -@Service(version = "1.2") -public class AnnotationServiceImpl implements DemoService { - - public String sayName(String name) { - return "annotation:" + name; - } - - public Box getBox() { - return null; - } - -} \ No newline at end of file +/* + * 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 com.alibaba.dubbo.config.spring.util; + +/** + * Object Utilities Class + * + * @since 2.5.11 + */ +public class ObjectUtils { + + /** + * of factory method + * + * @param values + * @param <T> + * @return + */ + public static <T> T[] of(T... values) { + return values; + } + +} diff --git a/dubbo-config/dubbo-config-spring/src/main/java/com/alibaba/dubbo/config/spring/util/PropertySourcesUtils.java b/dubbo-config/dubbo-config-spring/src/main/java/com/alibaba/dubbo/config/spring/util/PropertySourcesUtils.java index fe1c61b..5b183e1 100644 --- a/dubbo-config/dubbo-config-spring/src/main/java/com/alibaba/dubbo/config/spring/util/PropertySourcesUtils.java +++ b/dubbo-config/dubbo-config-spring/src/main/java/com/alibaba/dubbo/config/spring/util/PropertySourcesUtils.java @@ -35,16 +35,16 @@ public abstract class PropertySourcesUtils { /** * Get Sub {@link Properties} * - * @param propertySources {@link PropertySources} + * @param propertySources {@link PropertySource} Iterable * @param prefix the prefix of property name - * @return Map<String, String> + * @return Map<String , [...] * @see Properties */ - public static Map<String, String> getSubProperties(PropertySources propertySources, String prefix) { + public static Map<String, String> getSubProperties(Iterable<PropertySource<?>> propertySources, String prefix) { Map<String, String> subProperties = new LinkedHashMap<String, String>(); - String normalizedPrefix = prefix.endsWith(".") ? prefix : prefix + "."; + String normalizedPrefix = normalizePrefix(prefix); for (PropertySource<?> source : propertySources) { if (source instanceof EnumerablePropertySource) { @@ -62,4 +62,14 @@ public abstract class PropertySourcesUtils { } + /** + * Normalize the prefix + * + * @param prefix the prefix + * @return the prefix + */ + public static String normalizePrefix(String prefix) { + return prefix.endsWith(".") ? prefix : prefix + "."; + } + } diff --git a/dubbo-config/dubbo-config-spring/src/test/java/com/alibaba/dubbo/config/spring/annotation/provider/AnnotationServiceImpl.java b/dubbo-config/dubbo-config-spring/src/test/java/com/alibaba/dubbo/config/spring/annotation/provider/AnnotationServiceImpl.java index 7766a1a..327f4d9 100644 --- a/dubbo-config/dubbo-config-spring/src/test/java/com/alibaba/dubbo/config/spring/annotation/provider/AnnotationServiceImpl.java +++ b/dubbo-config/dubbo-config-spring/src/test/java/com/alibaba/dubbo/config/spring/annotation/provider/AnnotationServiceImpl.java @@ -23,7 +23,7 @@ import com.alibaba.dubbo.config.spring.api.DemoService; /** * DemoServiceImpl */ -@Service(version = "1.2") +@Service(version = "${provider.version}") public class AnnotationServiceImpl implements DemoService { public String sayName(String name) { diff --git a/dubbo-config/dubbo-config-spring/src/test/java/com/alibaba/dubbo/config/spring/beans/factory/annotation/AnnotationPropertyValuesAdapterTest.java b/dubbo-config/dubbo-config-spring/src/test/java/com/alibaba/dubbo/config/spring/beans/factory/annotation/AnnotationPropertyValuesAdapterTest.java new file mode 100644 index 0000000..36def71 --- /dev/null +++ b/dubbo-config/dubbo-config-spring/src/test/java/com/alibaba/dubbo/config/spring/beans/factory/annotation/AnnotationPropertyValuesAdapterTest.java @@ -0,0 +1,158 @@ +/* + * 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 com.alibaba.dubbo.config.spring.beans.factory.annotation; + + +import com.alibaba.dubbo.common.utils.CollectionUtils; +import com.alibaba.dubbo.config.annotation.Reference; +import com.alibaba.dubbo.config.spring.ReferenceBean; +import com.alibaba.dubbo.config.spring.api.DemoService; +import org.junit.Assert; +import org.junit.Test; +import org.springframework.core.annotation.AnnotationUtils; +import org.springframework.core.convert.converter.Converter; +import org.springframework.core.convert.support.DefaultConversionService; +import org.springframework.mock.env.MockEnvironment; +import org.springframework.util.ReflectionUtils; +import org.springframework.validation.DataBinder; + +import java.lang.reflect.Field; +import java.util.LinkedHashMap; +import java.util.Map; + +import static org.springframework.util.StringUtils.arrayToCommaDelimitedString; + +/** + * {@link AnnotationPropertyValuesAdapter} Test + * + * @since 2.5.11 + */ +public class AnnotationPropertyValuesAdapterTest { + + @Test + public void test() { + + MockEnvironment mockEnvironment = new MockEnvironment(); + + mockEnvironment.setProperty("version", "1.0.0"); + + mockEnvironment.setProperty("url", " dubbo://localhost:12345"); + + Field field = ReflectionUtils.findField(TestBean.class, "demoService"); + + Reference reference = AnnotationUtils.getAnnotation(field, Reference.class); + + AnnotationPropertyValuesAdapter propertyValues = new AnnotationPropertyValuesAdapter(reference, mockEnvironment); + + ReferenceBean referenceBean = new ReferenceBean(); + + DataBinder dataBinder = new DataBinder(referenceBean); + + dataBinder.setDisallowedFields("application", "module", "consumer", "monitor", "registry"); + + DefaultConversionService conversionService = new DefaultConversionService(); + + conversionService.addConverter(new Converter<String[], String>() { + @Override + public String convert(String[] source) { + return arrayToCommaDelimitedString(source); + } + }); + + conversionService.addConverter(new Converter<String[], Map<String, String>>() { + @Override + public Map<String, String> convert(String[] source) { + return CollectionUtils.toStringMap(source); + } + }); + + + dataBinder.setConversionService(conversionService); + + + dataBinder.bind(propertyValues); + +// System.out.println(referenceBean); + + Assert.assertEquals(DemoService.class, referenceBean.getInterfaceClass()); + Assert.assertEquals("com.alibaba.dubbo.config.spring.api.DemoService", referenceBean.getInterface()); + Assert.assertEquals("1.0.0", referenceBean.getVersion()); + Assert.assertEquals("group", referenceBean.getGroup()); + Assert.assertEquals("dubbo://localhost:12345", referenceBean.getUrl()); + Assert.assertEquals("client", referenceBean.getClient()); + Assert.assertEquals(true, referenceBean.isGeneric()); + Assert.assertEquals(true, referenceBean.isInjvm()); + Assert.assertEquals(false, referenceBean.isCheck()); + Assert.assertEquals(true, referenceBean.isInit()); + Assert.assertEquals(true, referenceBean.getLazy()); + Assert.assertEquals(true, referenceBean.getStubevent()); + Assert.assertEquals("reconnect", referenceBean.getReconnect()); + Assert.assertEquals(true, referenceBean.getSticky()); + + Assert.assertEquals("javassist", referenceBean.getProxy()); + + Assert.assertEquals("stub", referenceBean.getStub()); + Assert.assertEquals("failover", referenceBean.getCluster()); + Assert.assertEquals(Integer.valueOf(1), referenceBean.getConnections()); + Assert.assertEquals(Integer.valueOf(1), referenceBean.getCallbacks()); + Assert.assertEquals("onconnect", referenceBean.getOnconnect()); + Assert.assertEquals("ondisconnect", referenceBean.getOndisconnect()); + Assert.assertEquals("owner", referenceBean.getOwner()); + Assert.assertEquals("layer", referenceBean.getLayer()); + Assert.assertEquals(Integer.valueOf(2), referenceBean.getRetries()); + Assert.assertEquals("random", referenceBean.getLoadbalance()); + Assert.assertEquals(true, referenceBean.isAsync()); + Assert.assertEquals(Integer.valueOf(1), referenceBean.getActives()); + Assert.assertEquals(true, referenceBean.getSent()); + Assert.assertEquals("mock", referenceBean.getMock()); + Assert.assertEquals("validation", referenceBean.getValidation()); + Assert.assertEquals(Integer.valueOf(2), referenceBean.getTimeout()); + Assert.assertEquals("cache", referenceBean.getCache()); + Assert.assertEquals("default,default", referenceBean.getFilter()); + Assert.assertEquals("default,default", referenceBean.getListener()); + + Map<String, String> data = new LinkedHashMap<String, String>(); + data.put("key1", "value1"); + + Assert.assertEquals(data, referenceBean.getParameters()); + // Bean compare + Assert.assertEquals(null, referenceBean.getApplication()); + Assert.assertEquals(null, referenceBean.getModule()); + Assert.assertEquals(null, referenceBean.getConsumer()); + Assert.assertEquals(null, referenceBean.getMonitor()); + Assert.assertEquals(null, referenceBean.getRegistry()); + + } + + private static class TestBean { + + @Reference( + interfaceClass = DemoService.class, interfaceName = "com.alibaba.dubbo.config.spring.api.DemoService", version = "${version}", group = "group", + url = "${url} ", client = "client", generic = true, injvm = true, + check = false, init = true, lazy = true, stubevent = true, + reconnect = "reconnect", sticky = true, proxy = "javassist", stub = "stub", + cluster = "failover", connections = 1, callbacks = 1, onconnect = "onconnect", + ondisconnect = "ondisconnect", owner = "owner", layer = "layer", retries = 2, + loadbalance = "random", async = true, actives = 1, sent = true, + mock = "mock", validation = "validation", timeout = 2, cache = "cache", + filter = {"default", "default"}, listener = {"default", "default"}, parameters = {"key1", "value1"}, application = "application", + module = "module", consumer = "consumer", monitor = "monitor", registry = {"registry1", "registry2"} + ) + private DemoService demoService; + + } +} diff --git a/dubbo-config/dubbo-config-spring/src/test/java/com/alibaba/dubbo/config/spring/beans/factory/annotation/DubboConfigBindingBeanPostProcessorTest.java b/dubbo-config/dubbo-config-spring/src/test/java/com/alibaba/dubbo/config/spring/beans/factory/annotation/DubboConfigBindingBeanPostProcessorTest.java new file mode 100644 index 0000000..05a4980 --- /dev/null +++ b/dubbo-config/dubbo-config-spring/src/test/java/com/alibaba/dubbo/config/spring/beans/factory/annotation/DubboConfigBindingBeanPostProcessorTest.java @@ -0,0 +1,66 @@ +/* + * 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 com.alibaba.dubbo.config.spring.beans.factory.annotation; + +import com.alibaba.dubbo.config.ApplicationConfig; +import com.alibaba.dubbo.config.spring.context.properties.DefaultDubboConfigBinder; +import com.alibaba.dubbo.config.spring.context.properties.DubboConfigBinder; +import org.junit.Assert; +import org.junit.Test; +import org.springframework.context.annotation.AnnotationConfigApplicationContext; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.PropertySource; + +import static org.springframework.beans.factory.support.BeanDefinitionBuilder.rootBeanDefinition; + +/** + * {@link DubboConfigBindingBeanPostProcessor} + */ +@PropertySource({"classpath:/META-INF/config.properties"}) +@Configuration +public class DubboConfigBindingBeanPostProcessorTest { + + @Bean("applicationBean") + public ApplicationConfig applicationConfig() { + return new ApplicationConfig(); + } + + @Bean + public DubboConfigBinder dubboConfigBinder() { + return new DefaultDubboConfigBinder(); + } + + @Test + public void test() { + + final AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(); + + applicationContext.register(getClass()); + + Class<?> processorClass = DubboConfigBindingBeanPostProcessor.class; + + applicationContext.registerBeanDefinition("DubboConfigBindingBeanPostProcessor", rootBeanDefinition(processorClass).addConstructorArgValue("dubbo.application").addConstructorArgValue("applicationBean").getBeanDefinition()); + + applicationContext.refresh(); + + ApplicationConfig applicationConfig = applicationContext.getBean(ApplicationConfig.class); + + Assert.assertEquals("dubbo-demo-application", applicationConfig.getName()); + + } +} diff --git a/dubbo-config/dubbo-config-spring/src/test/java/com/alibaba/dubbo/config/spring/beans/factory/annotation/ReferenceAnnotationBeanPostProcessorTest.java b/dubbo-config/dubbo-config-spring/src/test/java/com/alibaba/dubbo/config/spring/beans/factory/annotation/ReferenceAnnotationBeanPostProcessorTest.java index 3f9a50e..5f33491 100644 --- a/dubbo-config/dubbo-config-spring/src/test/java/com/alibaba/dubbo/config/spring/beans/factory/annotation/ReferenceAnnotationBeanPostProcessorTest.java +++ b/dubbo-config/dubbo-config-spring/src/test/java/com/alibaba/dubbo/config/spring/beans/factory/annotation/ReferenceAnnotationBeanPostProcessorTest.java @@ -20,16 +20,16 @@ import com.alibaba.dubbo.config.annotation.Reference; import com.alibaba.dubbo.config.spring.ReferenceBean; import com.alibaba.dubbo.config.spring.api.DemoService; import com.alibaba.dubbo.config.spring.context.annotation.DubboComponentScan; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; +import org.junit.*; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.InjectionMetadata; import org.springframework.context.ApplicationContext; +import org.springframework.context.ConfigurableApplicationContext; import org.springframework.context.annotation.AnnotationConfigApplicationContext; import org.springframework.context.annotation.ImportResource; -import org.springframework.context.support.ClassPathXmlApplicationContext; import java.util.Collection; +import java.util.Map; import static com.alibaba.dubbo.config.spring.beans.factory.annotation.ReferenceAnnotationBeanPostProcessor.BEAN_NAME; @@ -40,12 +40,27 @@ import static com.alibaba.dubbo.config.spring.beans.factory.annotation.Reference */ public class ReferenceAnnotationBeanPostProcessorTest { - private static final String PROVIDER_LOCATION = "META-INF/spring/dubbo-provider.xml"; + private ConfigurableApplicationContext providerApplicationContext; + + @BeforeClass + public static void prepare() { + System.setProperty("provider.version", "1.2"); + System.setProperty("package1", "com.alibaba.dubbo.config.spring.annotation.provider"); + System.setProperty("packagesToScan", "${package1}"); + System.setProperty("consumer.version", "1.2"); + System.setProperty("consumer.url", "dubbo://127.0.0.1:12345"); + } @Before - public void before() { + public void init() { // Starts Provider - new ClassPathXmlApplicationContext(PROVIDER_LOCATION); + providerApplicationContext = new AnnotationConfigApplicationContext(ServiceAnnotationBeanPostProcessorTest.TestConfiguration.class); + } + + @After + public void destroy() { + // Shutdowns Provider + providerApplicationContext.close(); } @Test @@ -95,6 +110,66 @@ public class ReferenceAnnotationBeanPostProcessorTest { } + @Test + public void testGetInjectedFieldReferenceBeanMap() { + + AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(TestBean.class); + + ReferenceAnnotationBeanPostProcessor beanPostProcessor = context.getBean(BEAN_NAME, + ReferenceAnnotationBeanPostProcessor.class); + + + Map<InjectionMetadata.InjectedElement, ReferenceBean<?>> referenceBeanMap = + beanPostProcessor.getInjectedFieldReferenceBeanMap(); + + Assert.assertEquals(1, referenceBeanMap.size()); + + for (Map.Entry<InjectionMetadata.InjectedElement, ReferenceBean<?>> entry : referenceBeanMap.entrySet()) { + + InjectionMetadata.InjectedElement injectedElement = entry.getKey(); + + Assert.assertEquals("com.alibaba.dubbo.config.spring.beans.factory.annotation.ReferenceAnnotationBeanPostProcessor$ReferenceFieldElement", + injectedElement.getClass().getName()); + + ReferenceBean<?> referenceBean = entry.getValue(); + + Assert.assertEquals("1.2", referenceBean.getVersion()); + Assert.assertEquals("dubbo://127.0.0.1:12345", referenceBean.getUrl()); + + } + + } + + @Test + public void testGetInjectedMethodReferenceBeanMap() { + + AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(TestBean.class); + + ReferenceAnnotationBeanPostProcessor beanPostProcessor = context.getBean(BEAN_NAME, + ReferenceAnnotationBeanPostProcessor.class); + + + Map<InjectionMetadata.InjectedElement, ReferenceBean<?>> referenceBeanMap = + beanPostProcessor.getInjectedMethodReferenceBeanMap(); + + Assert.assertEquals(2, referenceBeanMap.size()); + + for (Map.Entry<InjectionMetadata.InjectedElement, ReferenceBean<?>> entry : referenceBeanMap.entrySet()) { + + InjectionMetadata.InjectedElement injectedElement = entry.getKey(); + + Assert.assertEquals("com.alibaba.dubbo.config.spring.beans.factory.annotation.ReferenceAnnotationBeanPostProcessor$ReferenceMethodElement", + injectedElement.getClass().getName()); + + ReferenceBean<?> referenceBean = entry.getValue(); + + Assert.assertEquals("1.2", referenceBean.getVersion()); + Assert.assertEquals("dubbo://127.0.0.1:12345", referenceBean.getUrl()); + + } + + } + private static class AncestorBean { @@ -121,7 +196,7 @@ public class ReferenceAnnotationBeanPostProcessorTest { private static class ParentBean extends AncestorBean { - @Reference(version = "1.2", url = "dubbo://127.0.0.1:12345") + @Reference(version = "${consumer.version}", url = "${consumer.url}") private DemoService demoServiceFromParent; public DemoService getDemoServiceFromParent() { @@ -133,7 +208,7 @@ public class ReferenceAnnotationBeanPostProcessorTest { @ImportResource("META-INF/spring/dubbo-annotation-consumer.xml") @DubboComponentScan(basePackageClasses = ReferenceAnnotationBeanPostProcessorTest.class) - private static class TestBean extends ParentBean { + static class TestBean extends ParentBean { private DemoService demoService; @@ -150,4 +225,4 @@ public class ReferenceAnnotationBeanPostProcessorTest { } } -} +} \ No newline at end of file diff --git a/dubbo-config/dubbo-config-spring/src/test/java/com/alibaba/dubbo/config/spring/beans/factory/annotation/ServiceAnnotationBeanPostProcessorTest.java b/dubbo-config/dubbo-config-spring/src/test/java/com/alibaba/dubbo/config/spring/beans/factory/annotation/ServiceAnnotationBeanPostProcessorTest.java index e5714c7..c096441 100644 --- a/dubbo-config/dubbo-config-spring/src/test/java/com/alibaba/dubbo/config/spring/beans/factory/annotation/ServiceAnnotationBeanPostProcessorTest.java +++ b/dubbo-config/dubbo-config-spring/src/test/java/com/alibaba/dubbo/config/spring/beans/factory/annotation/ServiceAnnotationBeanPostProcessorTest.java @@ -44,7 +44,8 @@ import java.util.Map; classes = {ServiceAnnotationBeanPostProcessorTest.TestConfiguration.class}) @TestPropertySource(properties = { "package1 = com.alibaba.dubbo.config.spring.context.annotation", - "packagesToScan = ${package1}" + "packagesToScan = ${package1}", + "provider.version = 1.2" }) public class ServiceAnnotationBeanPostProcessorTest { diff --git a/dubbo-config/dubbo-config-spring/src/test/java/com/alibaba/dubbo/config/spring/context/properties/DefaultDubboConfigBinderTest.java b/dubbo-config/dubbo-config-spring/src/test/java/com/alibaba/dubbo/config/spring/context/properties/DefaultDubboConfigBinderTest.java new file mode 100644 index 0000000..f0ec69f --- /dev/null +++ b/dubbo-config/dubbo-config-spring/src/test/java/com/alibaba/dubbo/config/spring/context/properties/DefaultDubboConfigBinderTest.java @@ -0,0 +1,56 @@ +/* + * 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 com.alibaba.dubbo.config.spring.context.properties; + + +import com.alibaba.dubbo.config.ApplicationConfig; +import com.alibaba.dubbo.config.ProtocolConfig; +import com.alibaba.dubbo.config.RegistryConfig; +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.TestPropertySource; +import org.springframework.test.context.junit4.SpringRunner; + +@RunWith(SpringRunner.class) +@TestPropertySource(locations = "classpath:/dubbo.properties") +@ContextConfiguration(classes = DefaultDubboConfigBinder.class) +public class DefaultDubboConfigBinderTest { + + @Autowired + private DubboConfigBinder dubboConfigBinder; + + @Test + public void testBinder() { + + ApplicationConfig applicationConfig = new ApplicationConfig(); + dubboConfigBinder.bind("dubbo.application", applicationConfig); + Assert.assertEquals("hello", applicationConfig.getName()); + Assert.assertEquals("world", applicationConfig.getOwner()); + + RegistryConfig registryConfig = new RegistryConfig(); + dubboConfigBinder.bind("dubbo.registry", registryConfig); + Assert.assertEquals("10.20.153.17", registryConfig.getAddress()); + + ProtocolConfig protocolConfig = new ProtocolConfig(); + dubboConfigBinder.bind("dubbo.protocol", protocolConfig); + Assert.assertEquals(Integer.valueOf(20881), protocolConfig.getPort()); + + } +} diff --git a/dubbo-config/dubbo-config-spring/src/test/java/com/alibaba/dubbo/config/spring/annotation/provider/AnnotationServiceImpl.java b/dubbo-config/dubbo-config-spring/src/test/java/com/alibaba/dubbo/config/spring/convert/converter/StringArrayToMapConverterTest.java similarity index 50% copy from dubbo-config/dubbo-config-spring/src/test/java/com/alibaba/dubbo/config/spring/annotation/provider/AnnotationServiceImpl.java copy to dubbo-config/dubbo-config-spring/src/test/java/com/alibaba/dubbo/config/spring/convert/converter/StringArrayToMapConverterTest.java index 7766a1a..51be7c3 100644 --- a/dubbo-config/dubbo-config-spring/src/test/java/com/alibaba/dubbo/config/spring/annotation/provider/AnnotationServiceImpl.java +++ b/dubbo-config/dubbo-config-spring/src/test/java/com/alibaba/dubbo/config/spring/convert/converter/StringArrayToMapConverterTest.java @@ -1,37 +1,52 @@ -/* - * 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 com.alibaba.dubbo.config.spring.annotation.provider; - -import com.alibaba.dubbo.config.annotation.Service; -import com.alibaba.dubbo.config.spring.api.Box; -import com.alibaba.dubbo.config.spring.api.DemoService; - -/** - * DemoServiceImpl - */ -@Service(version = "1.2") -public class AnnotationServiceImpl implements DemoService { - - public String sayName(String name) { - return "annotation:" + name; - } - - public Box getBox() { - return null; - } - -} \ No newline at end of file +/* + * 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 com.alibaba.dubbo.config.spring.convert.converter; + +import org.junit.Assert; +import org.junit.Test; + +import java.util.LinkedHashMap; +import java.util.Map; + +/** + * {@link StringArrayToMapConverter} Test + */ +public class StringArrayToMapConverterTest { + + @Test + public void testConvert() { + + StringArrayToMapConverter converter = new StringArrayToMapConverter(); + + Map<String, String> value = converter.convert(new String[]{"Hello", "World"}); + + Map<String, String> expected = new LinkedHashMap<String, String>(); + + expected.put("Hello", "World"); + + Assert.assertEquals(expected, value); + + value = converter.convert(new String[]{}); + + Assert.assertNull(value); + + value = converter.convert(null); + + Assert.assertNull(value); + + } +} diff --git a/dubbo-config/dubbo-config-spring/src/test/java/com/alibaba/dubbo/config/spring/annotation/provider/AnnotationServiceImpl.java b/dubbo-config/dubbo-config-spring/src/test/java/com/alibaba/dubbo/config/spring/convert/converter/StringArrayToStringConverterTest.java similarity index 56% copy from dubbo-config/dubbo-config-spring/src/test/java/com/alibaba/dubbo/config/spring/annotation/provider/AnnotationServiceImpl.java copy to dubbo-config/dubbo-config-spring/src/test/java/com/alibaba/dubbo/config/spring/convert/converter/StringArrayToStringConverterTest.java index 7766a1a..67e8247 100644 --- a/dubbo-config/dubbo-config-spring/src/test/java/com/alibaba/dubbo/config/spring/annotation/provider/AnnotationServiceImpl.java +++ b/dubbo-config/dubbo-config-spring/src/test/java/com/alibaba/dubbo/config/spring/convert/converter/StringArrayToStringConverterTest.java @@ -1,37 +1,46 @@ -/* - * 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 com.alibaba.dubbo.config.spring.annotation.provider; - -import com.alibaba.dubbo.config.annotation.Service; -import com.alibaba.dubbo.config.spring.api.Box; -import com.alibaba.dubbo.config.spring.api.DemoService; - -/** - * DemoServiceImpl - */ -@Service(version = "1.2") -public class AnnotationServiceImpl implements DemoService { - - public String sayName(String name) { - return "annotation:" + name; - } - - public Box getBox() { - return null; - } - -} \ No newline at end of file +/* + * 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 com.alibaba.dubbo.config.spring.convert.converter; + +import org.junit.Assert; +import org.junit.Test; + +/** + * {@link StringArrayToStringConverter} Test + */ +public class StringArrayToStringConverterTest { + + @Test + public void testConvert() { + + StringArrayToStringConverter converter = new StringArrayToStringConverter(); + + String value = converter.convert(new String[]{"Hello", "World"}); + + Assert.assertEquals("Hello,World", value); + + value = converter.convert(new String[]{}); + + Assert.assertNull(value); + + value = converter.convert(null); + + Assert.assertNull(value); + + } + +} -- To stop receiving notification emails like this one, please contact mercybl...@apache.org.