From e7a843f5632406db7bb05032e41087861f4092f8 Mon Sep 17 00:00:00 2001 From: mercyblitz Date: Mon, 14 Jan 2019 16:08:18 +0800 Subject: [PATCH] Polish apache/incubator-dubbo#3192 : inline the source code of spring-context-support --- dubbo-config/dubbo-config-spring/pom.xml | 7 +- .../AbstractAnnotationConfigBeanBuilder.java | 4 +- .../AnnotationInjectedBeanPostProcessor.java | 529 ++++++++++++++++++ .../AnnotationPropertyValuesAdapter.java | 2 +- .../ReferenceAnnotationBeanPostProcessor.java | 3 +- .../annotation/ReferenceBeanBuilder.java | 4 +- .../ServiceAnnotationBeanPostProcessor.java | 2 +- .../DubboConfigBindingRegistrar.java | 4 +- .../DubboConfigConfigurationRegistrar.java | 3 +- .../properties/DefaultDubboConfigBinder.java | 2 +- .../extension/SpringExtensionFactory.java | 222 ++++---- .../status/DataSourceStatusChecker.java | 192 +++---- .../spring/status/SpringStatusChecker.java | 184 +++--- .../AnnotatedBeanDefinitionRegistryUtils.java | 62 ++ .../config/spring/util/AnnotationUtils.java | 214 ++++++- .../config/spring/util/BeanFactoryUtils.java | 63 ++- .../config/spring/util/BeanRegistrar.java | 2 +- .../dubbo/config/spring/util/ClassUtils.java | 37 ++ .../dubbo/config/spring/util/ObjectUtils.java | 37 ++ .../spring/util/PropertySourcesUtils.java | 112 ++++ ...otatedBeanDefinitionRegistryUtilsTest.java | 59 ++ .../spring/util/PropertySourcesUtilsTest.java | 80 +++ 22 files changed, 1505 insertions(+), 319 deletions(-) create mode 100644 dubbo-config/dubbo-config-spring/src/main/java/com/alibaba/dubbo/config/spring/beans/factory/annotation/AnnotationInjectedBeanPostProcessor.java create mode 100644 dubbo-config/dubbo-config-spring/src/main/java/com/alibaba/dubbo/config/spring/util/AnnotatedBeanDefinitionRegistryUtils.java create mode 100644 dubbo-config/dubbo-config-spring/src/main/java/com/alibaba/dubbo/config/spring/util/ClassUtils.java create mode 100644 dubbo-config/dubbo-config-spring/src/main/java/com/alibaba/dubbo/config/spring/util/ObjectUtils.java create mode 100644 dubbo-config/dubbo-config-spring/src/main/java/com/alibaba/dubbo/config/spring/util/PropertySourcesUtils.java create mode 100644 dubbo-config/dubbo-config-spring/src/test/java/com/alibaba/dubbo/config/spring/util/AnnotatedBeanDefinitionRegistryUtilsTest.java create mode 100644 dubbo-config/dubbo-config-spring/src/test/java/com/alibaba/dubbo/config/spring/util/PropertySourcesUtilsTest.java diff --git a/dubbo-config/dubbo-config-spring/pom.xml b/dubbo-config/dubbo-config-spring/pom.xml index 420140257a5..b73627870a1 100644 --- a/dubbo-config/dubbo-config-spring/pom.xml +++ b/dubbo-config/dubbo-config-spring/pom.xml @@ -14,7 +14,8 @@ See the License for the specific language governing permissions and limitations under the License. --> - + 4.0.0 com.alibaba @@ -46,10 +47,6 @@ org.springframework spring-context - - com.alibaba.spring - spring-context-support - javax.servlet javax.servlet-api diff --git a/dubbo-config/dubbo-config-spring/src/main/java/com/alibaba/dubbo/config/spring/beans/factory/annotation/AbstractAnnotationConfigBeanBuilder.java b/dubbo-config/dubbo-config-spring/src/main/java/com/alibaba/dubbo/config/spring/beans/factory/annotation/AbstractAnnotationConfigBeanBuilder.java index 7a4129f4563..0357ff0bc3e 100644 --- a/dubbo-config/dubbo-config-spring/src/main/java/com/alibaba/dubbo/config/spring/beans/factory/annotation/AbstractAnnotationConfigBeanBuilder.java +++ b/dubbo-config/dubbo-config-spring/src/main/java/com/alibaba/dubbo/config/spring/beans/factory/annotation/AbstractAnnotationConfigBeanBuilder.java @@ -30,8 +30,8 @@ import java.lang.annotation.Annotation; import java.util.List; -import static com.alibaba.spring.util.BeanFactoryUtils.getBeans; -import static com.alibaba.spring.util.BeanFactoryUtils.getOptionalBean; +import static com.alibaba.dubbo.config.spring.util.BeanFactoryUtils.getBeans; +import static com.alibaba.dubbo.config.spring.util.BeanFactoryUtils.getOptionalBean; /** * Abstract Configurable {@link Annotation} Bean Builder diff --git a/dubbo-config/dubbo-config-spring/src/main/java/com/alibaba/dubbo/config/spring/beans/factory/annotation/AnnotationInjectedBeanPostProcessor.java b/dubbo-config/dubbo-config-spring/src/main/java/com/alibaba/dubbo/config/spring/beans/factory/annotation/AnnotationInjectedBeanPostProcessor.java new file mode 100644 index 00000000000..95ecdfb0a84 --- /dev/null +++ b/dubbo-config/dubbo-config-spring/src/main/java/com/alibaba/dubbo/config/spring/beans/factory/annotation/AnnotationInjectedBeanPostProcessor.java @@ -0,0 +1,529 @@ +/* + * 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.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.springframework.beans.BeanUtils; +import org.springframework.beans.BeansException; +import org.springframework.beans.PropertyValues; +import org.springframework.beans.factory.BeanClassLoaderAware; +import org.springframework.beans.factory.BeanCreationException; +import org.springframework.beans.factory.BeanFactory; +import org.springframework.beans.factory.BeanFactoryAware; +import org.springframework.beans.factory.DisposableBean; +import org.springframework.beans.factory.annotation.InjectionMetadata; +import org.springframework.beans.factory.config.BeanPostProcessor; +import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; +import org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessorAdapter; +import org.springframework.beans.factory.support.MergedBeanDefinitionPostProcessor; +import org.springframework.beans.factory.support.RootBeanDefinition; +import org.springframework.context.EnvironmentAware; +import org.springframework.core.Ordered; +import org.springframework.core.PriorityOrdered; +import org.springframework.core.env.Environment; +import org.springframework.util.Assert; +import org.springframework.util.ClassUtils; +import org.springframework.util.ReflectionUtils; +import org.springframework.util.StringUtils; + +import java.beans.PropertyDescriptor; +import java.lang.annotation.Annotation; +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.LinkedHashMap; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; + +import static com.alibaba.dubbo.config.spring.util.ClassUtils.resolveGenericType; +import static org.springframework.core.BridgeMethodResolver.findBridgedMethod; +import static org.springframework.core.BridgeMethodResolver.isVisibilityBridgeMethodPair; +import static org.springframework.core.annotation.AnnotationUtils.findAnnotation; +import static org.springframework.core.annotation.AnnotationUtils.getAnnotation; + +/** + * Abstract generic {@link BeanPostProcessor} implementation for customized annotation that annotated injected-object. + * + * The source code is cloned from https://github.com/alibaba/spring-context-support/blob/1.0.2/src/main/java/com/alibaba/spring/beans/factory/annotation/AnnotationInjectedBeanPostProcessor.java + * + * @since 2.6.6 + */ +public abstract class AnnotationInjectedBeanPostProcessor extends + InstantiationAwareBeanPostProcessorAdapter implements MergedBeanDefinitionPostProcessor, PriorityOrdered, + BeanFactoryAware, BeanClassLoaderAware, EnvironmentAware, DisposableBean { + + private final static int CACHE_SIZE = Integer.getInteger("", 32); + + private final Log logger = LogFactory.getLog(getClass()); + + private final Class annotationType; + + private final ConcurrentMap injectionMetadataCache = + new ConcurrentHashMap(CACHE_SIZE); + + private final ConcurrentMap injectedObjectsCache = new ConcurrentHashMap(CACHE_SIZE); + + private ConfigurableListableBeanFactory beanFactory; + + private Environment environment; + + private ClassLoader classLoader; + + private int order = Ordered.LOWEST_PRECEDENCE; + + public AnnotationInjectedBeanPostProcessor() { + this.annotationType = resolveGenericType(getClass()); + } + + private static Collection combine(Collection... elements) { + List allElements = new ArrayList(); + for (Collection e : elements) { + allElements.addAll(e); + } + return allElements; + } + + /** + * Annotation type + * + * @return non-null + */ + public final Class getAnnotationType() { + return annotationType; + } + + public void setBeanFactory(BeanFactory beanFactory) throws BeansException { + Assert.isInstanceOf(ConfigurableListableBeanFactory.class, beanFactory, + "AnnotationInjectedBeanPostProcessor requires a ConfigurableListableBeanFactory"); + this.beanFactory = (ConfigurableListableBeanFactory) beanFactory; + } + + @Override + public PropertyValues postProcessPropertyValues( + PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeanCreationException { + + InjectionMetadata metadata = findInjectionMetadata(beanName, bean.getClass(), pvs); + try { + metadata.inject(bean, beanName, pvs); + } catch (BeanCreationException ex) { + throw ex; + } catch (Throwable ex) { + throw new BeanCreationException(beanName, "Injection of @" + getAnnotationType().getName() + + " dependencies is failed", ex); + } + return pvs; + } + + + /** + * Finds {@link InjectionMetadata.InjectedElement} Metadata from annotated {@link A} fields + * + * @param beanClass The {@link Class} of Bean + * @return non-null {@link List} + */ + private List findFieldAnnotationMetadata(final Class beanClass) { + + final List elements = new LinkedList(); + + ReflectionUtils.doWithFields(beanClass, new ReflectionUtils.FieldCallback() { + @Override + public void doWith(Field field) throws IllegalArgumentException, IllegalAccessException { + + A annotation = getAnnotation(field, getAnnotationType()); + + if (annotation != null) { + + if (Modifier.isStatic(field.getModifiers())) { + if (logger.isWarnEnabled()) { + logger.warn("@" + getAnnotationType().getName() + " is not supported on static fields: " + field); + } + return; + } + + elements.add(new AnnotationInjectedBeanPostProcessor.AnnotatedFieldElement(field, annotation)); + } + + } + }); + + return elements; + + } + + /** + * Finds {@link InjectionMetadata.InjectedElement} Metadata from annotated {@link A @A} methods + * + * @param beanClass The {@link Class} of Bean + * @return non-null {@link List} + */ + private List findAnnotatedMethodMetadata(final Class beanClass) { + + final List elements = new LinkedList(); + + ReflectionUtils.doWithMethods(beanClass, new ReflectionUtils.MethodCallback() { + @Override + public void doWith(Method method) throws IllegalArgumentException, IllegalAccessException { + + Method bridgedMethod = findBridgedMethod(method); + + if (!isVisibilityBridgeMethodPair(method, bridgedMethod)) { + return; + } + + A annotation = findAnnotation(bridgedMethod, getAnnotationType()); + + if (annotation != null && method.equals(ClassUtils.getMostSpecificMethod(method, beanClass))) { + if (Modifier.isStatic(method.getModifiers())) { + if (logger.isWarnEnabled()) { + logger.warn("@" + getAnnotationType().getSimpleName() + " annotation is not supported on static methods: " + method); + } + return; + } + if (method.getParameterTypes().length == 0) { + if (logger.isWarnEnabled()) { + logger.warn("@" + getAnnotationType().getSimpleName() + " annotation should only be used on methods with parameters: " + + method); + } + } + PropertyDescriptor pd = BeanUtils.findPropertyForMethod(bridgedMethod, beanClass); + elements.add(new AnnotationInjectedBeanPostProcessor.AnnotatedMethodElement(method, pd, annotation)); + } + } + }); + + return elements; + + } + + + private AnnotationInjectedBeanPostProcessor.AnnotatedInjectionMetadata buildAnnotatedMetadata(final Class beanClass) { + Collection fieldElements = findFieldAnnotationMetadata(beanClass); + Collection methodElements = findAnnotatedMethodMetadata(beanClass); + return new AnnotationInjectedBeanPostProcessor.AnnotatedInjectionMetadata(beanClass, fieldElements, methodElements); + + } + + private InjectionMetadata findInjectionMetadata(String beanName, Class clazz, PropertyValues pvs) { + // 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. + AnnotationInjectedBeanPostProcessor.AnnotatedInjectionMetadata metadata = this.injectionMetadataCache.get(cacheKey); + if (InjectionMetadata.needsRefresh(metadata, clazz)) { + synchronized (this.injectionMetadataCache) { + metadata = this.injectionMetadataCache.get(cacheKey); + if (InjectionMetadata.needsRefresh(metadata, clazz)) { + if (metadata != null) { + metadata.clear(pvs); + } + try { + metadata = buildAnnotatedMetadata(clazz); + this.injectionMetadataCache.put(cacheKey, metadata); + } catch (NoClassDefFoundError err) { + throw new IllegalStateException("Failed to introspect object class [" + clazz.getName() + + "] for annotation metadata: could not find class that it depends on", err); + } + } + } + } + return metadata; + } + + @Override + public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class beanType, String beanName) { + if (beanType != null) { + InjectionMetadata metadata = findInjectionMetadata(beanName, beanType, null); + metadata.checkConfigMembers(beanDefinition); + } + } + + @Override + public int getOrder() { + return order; + } + + public void setOrder(int order) { + this.order = order; + } + + @Override + public void destroy() throws Exception { + + for (Object object : injectedObjectsCache.values()) { + if (logger.isInfoEnabled()) { + logger.info(object + " was destroying!"); + } + + if (object instanceof DisposableBean) { + ((DisposableBean) object).destroy(); + } + } + + injectionMetadataCache.clear(); + injectedObjectsCache.clear(); + + if (logger.isInfoEnabled()) { + logger.info(getClass() + " was destroying!"); + } + + } + + @Override + public void setBeanClassLoader(ClassLoader classLoader) { + this.classLoader = classLoader; + } + + public void setEnvironment(Environment environment) { + this.environment = environment; + } + + protected Environment getEnvironment() { + return environment; + } + + protected ClassLoader getClassLoader() { + return classLoader; + } + + protected ConfigurableListableBeanFactory getBeanFactory() { + return beanFactory; + } + + /** + * Gets all injected-objects. + * + * @return non-null {@link Collection} + */ + protected Collection getInjectedObjects() { + return this.injectedObjectsCache.values(); + } + + /** + * Get injected-object from specified {@link A annotation} and Bean Class + * + * @param annotation {@link A annotation} + * @param bean Current bean that will be injected + * @param beanName Current bean name that will be injected + * @param injectedType the type of injected-object + * @param injectedElement {@link InjectionMetadata.InjectedElement} + * @return An injected object + * @throws Exception If getting is failed + */ + protected Object getInjectedObject(A annotation, Object bean, String beanName, Class injectedType, + InjectionMetadata.InjectedElement injectedElement) throws Exception { + + String cacheKey = buildInjectedObjectCacheKey(annotation, bean, beanName, injectedType, injectedElement); + + Object injectedObject = injectedObjectsCache.get(cacheKey); + + if (injectedObject == null) { + injectedObject = doGetInjectedBean(annotation, bean, beanName, injectedType, injectedElement); + // Customized inject-object if necessary + injectedObjectsCache.putIfAbsent(cacheKey, injectedObject); + } + + return injectedObject; + + } + + /** + * Subclass must implement this method to get injected-object. The context objects could help this method if + * necessary : + *
    + *
  • {@link #getBeanFactory() BeanFactory}
  • + *
  • {@link #getClassLoader() ClassLoader}
  • + *
  • {@link #getEnvironment() Environment}
  • + *
+ * + * @param annotation {@link A annotation} + * @param bean Current bean that will be injected + * @param beanName Current bean name that will be injected + * @param injectedType the type of injected-object + * @param injectedElement {@link InjectionMetadata.InjectedElement} + * @return The injected object + * @throws Exception If resolving an injected object is failed. + */ + protected abstract Object doGetInjectedBean(A annotation, Object bean, String beanName, Class injectedType, + InjectionMetadata.InjectedElement injectedElement) throws Exception; + + /** + * Build a cache key for injected-object. The context objects could help this method if + * necessary : + *
    + *
  • {@link #getBeanFactory() BeanFactory}
  • + *
  • {@link #getClassLoader() ClassLoader}
  • + *
  • {@link #getEnvironment() Environment}
  • + *
+ * + * @param annotation {@link A annotation} + * @param bean Current bean that will be injected + * @param beanName Current bean name that will be injected + * @param injectedType the type of injected-object + * @param injectedElement {@link InjectionMetadata.InjectedElement} + * @return Bean cache key + */ + protected abstract String buildInjectedObjectCacheKey(A annotation, Object bean, String beanName, + Class injectedType, + InjectionMetadata.InjectedElement injectedElement); + + /** + * Get {@link Map} in injected field. + * + * @return non-null ready-only {@link Map} + */ + protected Map getInjectedFieldObjectsMap() { + + Map injectedElementBeanMap = + new LinkedHashMap(); + + for (AnnotationInjectedBeanPostProcessor.AnnotatedInjectionMetadata metadata : injectionMetadataCache.values()) { + + Collection fieldElements = metadata.getFieldElements(); + + for (AnnotationInjectedBeanPostProcessor.AnnotatedFieldElement fieldElement : fieldElements) { + + injectedElementBeanMap.put(fieldElement, fieldElement.bean); + + } + + } + + return Collections.unmodifiableMap(injectedElementBeanMap); + + } + + /** + * Get {@link Map} in injected method. + * + * @return non-null {@link Map} + */ + protected Map getInjectedMethodObjectsMap() { + + Map injectedElementBeanMap = + new LinkedHashMap(); + + for (AnnotationInjectedBeanPostProcessor.AnnotatedInjectionMetadata metadata : injectionMetadataCache.values()) { + + Collection methodElements = metadata.getMethodElements(); + + for (AnnotationInjectedBeanPostProcessor.AnnotatedMethodElement methodElement : methodElements) { + + injectedElementBeanMap.put(methodElement, methodElement.object); + + } + + } + + return Collections.unmodifiableMap(injectedElementBeanMap); + + } + + /** + * {@link A} {@link InjectionMetadata} implementation + */ + private class AnnotatedInjectionMetadata extends InjectionMetadata { + + private final Collection fieldElements; + + private final Collection methodElements; + + public AnnotatedInjectionMetadata(Class targetClass, Collection fieldElements, + Collection methodElements) { + super(targetClass, combine(fieldElements, methodElements)); + this.fieldElements = fieldElements; + this.methodElements = methodElements; + } + + public Collection getFieldElements() { + return fieldElements; + } + + public Collection getMethodElements() { + return methodElements; + } + } + + /** + * {@link A} {@link Method} {@link InjectionMetadata.InjectedElement} + */ + private class AnnotatedMethodElement extends InjectionMetadata.InjectedElement { + + private final Method method; + + private final A annotation; + + private volatile Object object; + + protected AnnotatedMethodElement(Method method, PropertyDescriptor pd, A annotation) { + super(method, pd); + this.method = method; + this.annotation = annotation; + } + + @Override + protected void inject(Object bean, String beanName, PropertyValues pvs) throws Throwable { + + Class injectedType = pd.getPropertyType(); + + Object injectedObject = getInjectedObject(annotation, bean, beanName, injectedType, this); + + ReflectionUtils.makeAccessible(method); + + method.invoke(bean, injectedObject); + + } + + } + + /** + * {@link A} {@link Field} {@link InjectionMetadata.InjectedElement} + */ + public class AnnotatedFieldElement extends InjectionMetadata.InjectedElement { + + private final Field field; + + private final A annotation; + + private volatile Object bean; + + protected AnnotatedFieldElement(Field field, A annotation) { + super(field, null); + this.field = field; + this.annotation = annotation; + } + + @Override + protected void inject(Object bean, String beanName, PropertyValues pvs) throws Throwable { + + Class injectedType = field.getType(); + + Object injectedObject = getInjectedObject(annotation, bean, beanName, injectedType, this); + + ReflectionUtils.makeAccessible(field); + + field.set(bean, injectedObject); + + } + + } +} 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 index 29a8acc7eb5..aab1883a71e 100644 --- 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 @@ -23,7 +23,7 @@ import java.lang.annotation.Annotation; -import static com.alibaba.spring.util.AnnotationUtils.getAttributes; +import static com.alibaba.dubbo.config.spring.util.AnnotationUtils.getAttributes; /** 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 517c62571ea..54c981e8103 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 @@ -20,8 +20,7 @@ import com.alibaba.dubbo.config.spring.ReferenceBean; import com.alibaba.dubbo.config.spring.ServiceBean; import com.alibaba.dubbo.config.spring.context.event.ServiceBeanExportedEvent; -import com.alibaba.spring.beans.factory.annotation.AnnotationInjectedBeanPostProcessor; -import com.alibaba.spring.util.AnnotationUtils; +import com.alibaba.dubbo.config.spring.util.AnnotationUtils; import org.springframework.beans.BeansException; import org.springframework.beans.factory.annotation.InjectionMetadata; 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 7b5288dfa9e..9b92d214169 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 @@ -31,8 +31,8 @@ import java.beans.PropertyEditorSupport; import java.util.Map; -import static com.alibaba.spring.util.BeanFactoryUtils.getOptionalBean; -import static com.alibaba.spring.util.ObjectUtils.of; +import static com.alibaba.dubbo.config.spring.util.BeanFactoryUtils.getOptionalBean; +import static com.alibaba.dubbo.config.spring.util.ObjectUtils.of; import static org.springframework.util.StringUtils.commaDelimitedListToStringArray; /** 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 d34b4a60e7f..b39d23f7da9 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 @@ -57,7 +57,7 @@ import java.util.List; import java.util.Set; -import static com.alibaba.spring.util.ObjectUtils.of; +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; 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 8e8cf202f6e..5e1c18ef81a 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 @@ -41,8 +41,8 @@ import java.util.Map; import java.util.Set; -import static com.alibaba.spring.util.PropertySourcesUtils.getSubProperties; -import static com.alibaba.spring.util.PropertySourcesUtils.normalizePrefix; +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; diff --git a/dubbo-config/dubbo-config-spring/src/main/java/com/alibaba/dubbo/config/spring/context/annotation/DubboConfigConfigurationRegistrar.java b/dubbo-config/dubbo-config-spring/src/main/java/com/alibaba/dubbo/config/spring/context/annotation/DubboConfigConfigurationRegistrar.java index b18692bd12e..fc292411db2 100644 --- a/dubbo-config/dubbo-config-spring/src/main/java/com/alibaba/dubbo/config/spring/context/annotation/DubboConfigConfigurationRegistrar.java +++ b/dubbo-config/dubbo-config-spring/src/main/java/com/alibaba/dubbo/config/spring/context/annotation/DubboConfigConfigurationRegistrar.java @@ -26,7 +26,8 @@ import org.springframework.core.env.Environment; import org.springframework.core.type.AnnotationMetadata; -import static com.alibaba.spring.util.AnnotatedBeanDefinitionRegistryUtils.registerBeans; +import static com.alibaba.dubbo.config.spring.util.AnnotatedBeanDefinitionRegistryUtils.registerBeans; + /** * Dubbo {@link AbstractConfig Config} {@link ImportBeanDefinitionRegistrar register}, which order can be configured 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 index 045a5acbb6a..cda2a6eeff9 100644 --- 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 @@ -23,7 +23,7 @@ import java.util.Map; -import static com.alibaba.spring.util.PropertySourcesUtils.getSubProperties; +import static com.alibaba.dubbo.config.spring.util.PropertySourcesUtils.getSubProperties; /** * Default {@link DubboConfigBinder} implementation based on Spring {@link DataBinder} diff --git a/dubbo-config/dubbo-config-spring/src/main/java/com/alibaba/dubbo/config/spring/extension/SpringExtensionFactory.java b/dubbo-config/dubbo-config-spring/src/main/java/com/alibaba/dubbo/config/spring/extension/SpringExtensionFactory.java index 5cbc06e35af..c6a07de62d5 100644 --- a/dubbo-config/dubbo-config-spring/src/main/java/com/alibaba/dubbo/config/spring/extension/SpringExtensionFactory.java +++ b/dubbo-config/dubbo-config-spring/src/main/java/com/alibaba/dubbo/config/spring/extension/SpringExtensionFactory.java @@ -1,111 +1,111 @@ -/* - * 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.extension; - -import com.alibaba.dubbo.common.extension.ExtensionFactory; -import com.alibaba.dubbo.common.logger.Logger; -import com.alibaba.dubbo.common.logger.LoggerFactory; -import com.alibaba.dubbo.common.utils.ConcurrentHashSet; - -import com.alibaba.dubbo.config.DubboShutdownHook; -import com.alibaba.dubbo.config.spring.util.BeanFactoryUtils; -import org.springframework.beans.factory.NoSuchBeanDefinitionException; -import org.springframework.beans.factory.NoUniqueBeanDefinitionException; -import org.springframework.context.ApplicationContext; -import org.springframework.context.ApplicationEvent; -import org.springframework.context.ApplicationListener; -import org.springframework.context.event.ContextClosedEvent; - -import java.util.Set; - -/** - * SpringExtensionFactory - */ -public class SpringExtensionFactory implements ExtensionFactory { - private static final Logger logger = LoggerFactory.getLogger(SpringExtensionFactory.class); - - private static final Set contexts = new ConcurrentHashSet(); - - private static final ApplicationListener shutdownHookListener = new ShutdownHookListener(); - - public static void addApplicationContext(ApplicationContext context) { - contexts.add(context); - BeanFactoryUtils.addApplicationListener(context, shutdownHookListener); - } - - public static void removeApplicationContext(ApplicationContext context) { - contexts.remove(context); - } - - public static Set getContexts() { - return contexts; - } - - // currently for test purpose - public static void clearContexts() { - contexts.clear(); - } - - @Override - @SuppressWarnings("unchecked") - public T getExtension(Class type, String name) { - for (ApplicationContext context : contexts) { - if (context.containsBean(name)) { - Object bean = context.getBean(name); - if (type.isInstance(bean)) { - return (T) bean; - } - } - } - - logger.warn("No spring extension (bean) named:" + name + ", try to find an extension (bean) of type " + type.getName()); - - if (Object.class == type) { - return null; - } - - for (ApplicationContext context : contexts) { - try { - return context.getBean(type); - } catch (NoUniqueBeanDefinitionException multiBeanExe) { - logger.warn("Find more than 1 spring extensions (beans) of type " + type.getName() + ", will stop auto injection. Please make sure you have specified the concrete parameter type and there's only one extension of that type."); - } catch (NoSuchBeanDefinitionException noBeanExe) { - if (logger.isDebugEnabled()) { - logger.debug("Error when get spring extension(bean) for type:" + type.getName(), noBeanExe); - } - } - } - - logger.warn("No spring extension (bean) named:" + name + ", type:" + type.getName() + " found, stop get bean."); - - return null; - } - - private static class ShutdownHookListener implements ApplicationListener { - @Override - public void onApplicationEvent(ApplicationEvent event) { - if (event instanceof ContextClosedEvent) { - // we call it anyway since dubbo shutdown hook make sure its destroyAll() is re-entrant. - // pls. note we should not remove dubbo shutdown hook when spring framework is present, this is because - // its shutdown hook may not be installed. - DubboShutdownHook shutdownHook = DubboShutdownHook.getDubboShutdownHook(); - shutdownHook.destroyAll(); - } - } - } - -} +/* + * 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.extension; + +import com.alibaba.dubbo.common.extension.ExtensionFactory; +import com.alibaba.dubbo.common.logger.Logger; +import com.alibaba.dubbo.common.logger.LoggerFactory; +import com.alibaba.dubbo.common.utils.ConcurrentHashSet; +import com.alibaba.dubbo.config.DubboShutdownHook; +import com.alibaba.dubbo.config.spring.util.BeanFactoryUtils; + +import org.springframework.beans.factory.NoSuchBeanDefinitionException; +import org.springframework.beans.factory.NoUniqueBeanDefinitionException; +import org.springframework.context.ApplicationContext; +import org.springframework.context.ApplicationEvent; +import org.springframework.context.ApplicationListener; +import org.springframework.context.event.ContextClosedEvent; + +import java.util.Set; + +/** + * SpringExtensionFactory + */ +public class SpringExtensionFactory implements ExtensionFactory { + private static final Logger logger = LoggerFactory.getLogger(SpringExtensionFactory.class); + + private static final Set contexts = new ConcurrentHashSet(); + + private static final ApplicationListener shutdownHookListener = new ShutdownHookListener(); + + public static void addApplicationContext(ApplicationContext context) { + contexts.add(context); + BeanFactoryUtils.addApplicationListener(context, shutdownHookListener); + } + + public static void removeApplicationContext(ApplicationContext context) { + contexts.remove(context); + } + + public static Set getContexts() { + return contexts; + } + + // currently for test purpose + public static void clearContexts() { + contexts.clear(); + } + + @Override + @SuppressWarnings("unchecked") + public T getExtension(Class type, String name) { + for (ApplicationContext context : contexts) { + if (context.containsBean(name)) { + Object bean = context.getBean(name); + if (type.isInstance(bean)) { + return (T) bean; + } + } + } + + logger.warn("No spring extension (bean) named:" + name + ", try to find an extension (bean) of type " + type.getName()); + + if (Object.class == type) { + return null; + } + + for (ApplicationContext context : contexts) { + try { + return context.getBean(type); + } catch (NoUniqueBeanDefinitionException multiBeanExe) { + logger.warn("Find more than 1 spring extensions (beans) of type " + type.getName() + ", will stop auto injection. Please make sure you have specified the concrete parameter type and there's only one extension of that type."); + } catch (NoSuchBeanDefinitionException noBeanExe) { + if (logger.isDebugEnabled()) { + logger.debug("Error when get spring extension(bean) for type:" + type.getName(), noBeanExe); + } + } + } + + logger.warn("No spring extension (bean) named:" + name + ", type:" + type.getName() + " found, stop get bean."); + + return null; + } + + private static class ShutdownHookListener implements ApplicationListener { + @Override + public void onApplicationEvent(ApplicationEvent event) { + if (event instanceof ContextClosedEvent) { + // we call it anyway since dubbo shutdown hook make sure its destroyAll() is re-entrant. + // pls. note we should not remove dubbo shutdown hook when spring framework is present, this is because + // its shutdown hook may not be installed. + DubboShutdownHook shutdownHook = DubboShutdownHook.getDubboShutdownHook(); + shutdownHook.destroyAll(); + } + } + } + +} diff --git a/dubbo-config/dubbo-config-spring/src/main/java/com/alibaba/dubbo/config/spring/status/DataSourceStatusChecker.java b/dubbo-config/dubbo-config-spring/src/main/java/com/alibaba/dubbo/config/spring/status/DataSourceStatusChecker.java index 32baa41da48..8863d8b2d6a 100644 --- a/dubbo-config/dubbo-config-spring/src/main/java/com/alibaba/dubbo/config/spring/status/DataSourceStatusChecker.java +++ b/dubbo-config/dubbo-config-spring/src/main/java/com/alibaba/dubbo/config/spring/status/DataSourceStatusChecker.java @@ -1,96 +1,96 @@ -/* - * 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.status; - -import com.alibaba.dubbo.common.extension.Activate; -import com.alibaba.dubbo.common.logger.Logger; -import com.alibaba.dubbo.common.logger.LoggerFactory; -import com.alibaba.dubbo.common.status.Status; -import com.alibaba.dubbo.common.status.StatusChecker; - -import com.alibaba.dubbo.config.spring.extension.SpringExtensionFactory; -import org.springframework.context.ApplicationContext; - -import javax.sql.DataSource; -import java.sql.Connection; -import java.sql.DatabaseMetaData; -import java.sql.ResultSet; -import java.util.Map; - -/** - * DataSourceStatusChecker - */ -@Activate -public class DataSourceStatusChecker implements StatusChecker { - - private static final Logger logger = LoggerFactory.getLogger(DataSourceStatusChecker.class); - - @Override - @SuppressWarnings("unchecked") - public Status check() { - ApplicationContext context = null; - for (ApplicationContext c : SpringExtensionFactory.getContexts()) { - if (c != null) { - context = c; - break; - } - } - if (context == null) { - return new Status(Status.Level.UNKNOWN); - } - Map dataSources = context.getBeansOfType(DataSource.class, false, false); - if (dataSources == null || dataSources.size() == 0) { - return new Status(Status.Level.UNKNOWN); - } - Status.Level level = Status.Level.OK; - StringBuilder buf = new StringBuilder(); - for (Map.Entry entry : dataSources.entrySet()) { - DataSource dataSource = entry.getValue(); - if (buf.length() > 0) { - buf.append(", "); - } - buf.append(entry.getKey()); - try { - Connection connection = dataSource.getConnection(); - try { - DatabaseMetaData metaData = connection.getMetaData(); - ResultSet resultSet = metaData.getTypeInfo(); - try { - if (!resultSet.next()) { - level = Status.Level.ERROR; - } - } finally { - resultSet.close(); - } - buf.append(metaData.getURL()); - buf.append("("); - buf.append(metaData.getDatabaseProductName()); - buf.append("-"); - buf.append(metaData.getDatabaseProductVersion()); - buf.append(")"); - } finally { - connection.close(); - } - } catch (Throwable e) { - logger.warn(e.getMessage(), e); - return new Status(level, e.getMessage()); - } - } - return new Status(level, buf.toString()); - } - -} +/* + * 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.status; + +import com.alibaba.dubbo.common.extension.Activate; +import com.alibaba.dubbo.common.logger.Logger; +import com.alibaba.dubbo.common.logger.LoggerFactory; +import com.alibaba.dubbo.common.status.Status; +import com.alibaba.dubbo.common.status.StatusChecker; +import com.alibaba.dubbo.config.spring.extension.SpringExtensionFactory; + +import org.springframework.context.ApplicationContext; + +import javax.sql.DataSource; +import java.sql.Connection; +import java.sql.DatabaseMetaData; +import java.sql.ResultSet; +import java.util.Map; + +/** + * DataSourceStatusChecker + */ +@Activate +public class DataSourceStatusChecker implements StatusChecker { + + private static final Logger logger = LoggerFactory.getLogger(DataSourceStatusChecker.class); + + @Override + @SuppressWarnings("unchecked") + public Status check() { + ApplicationContext context = null; + for (ApplicationContext c : SpringExtensionFactory.getContexts()) { + if (c != null) { + context = c; + break; + } + } + if (context == null) { + return new Status(Status.Level.UNKNOWN); + } + Map dataSources = context.getBeansOfType(DataSource.class, false, false); + if (dataSources == null || dataSources.size() == 0) { + return new Status(Status.Level.UNKNOWN); + } + Status.Level level = Status.Level.OK; + StringBuilder buf = new StringBuilder(); + for (Map.Entry entry : dataSources.entrySet()) { + DataSource dataSource = entry.getValue(); + if (buf.length() > 0) { + buf.append(", "); + } + buf.append(entry.getKey()); + try { + Connection connection = dataSource.getConnection(); + try { + DatabaseMetaData metaData = connection.getMetaData(); + ResultSet resultSet = metaData.getTypeInfo(); + try { + if (!resultSet.next()) { + level = Status.Level.ERROR; + } + } finally { + resultSet.close(); + } + buf.append(metaData.getURL()); + buf.append("("); + buf.append(metaData.getDatabaseProductName()); + buf.append("-"); + buf.append(metaData.getDatabaseProductVersion()); + buf.append(")"); + } finally { + connection.close(); + } + } catch (Throwable e) { + logger.warn(e.getMessage(), e); + return new Status(level, e.getMessage()); + } + } + return new Status(level, buf.toString()); + } + +} diff --git a/dubbo-config/dubbo-config-spring/src/main/java/com/alibaba/dubbo/config/spring/status/SpringStatusChecker.java b/dubbo-config/dubbo-config-spring/src/main/java/com/alibaba/dubbo/config/spring/status/SpringStatusChecker.java index f80b5e6b806..282f3644fc3 100644 --- a/dubbo-config/dubbo-config-spring/src/main/java/com/alibaba/dubbo/config/spring/status/SpringStatusChecker.java +++ b/dubbo-config/dubbo-config-spring/src/main/java/com/alibaba/dubbo/config/spring/status/SpringStatusChecker.java @@ -1,92 +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.status; - -import com.alibaba.dubbo.common.extension.Activate; -import com.alibaba.dubbo.common.logger.Logger; -import com.alibaba.dubbo.common.logger.LoggerFactory; -import com.alibaba.dubbo.common.status.Status; -import com.alibaba.dubbo.common.status.StatusChecker; - -import com.alibaba.dubbo.config.spring.extension.SpringExtensionFactory; -import org.springframework.context.ApplicationContext; -import org.springframework.context.Lifecycle; - -import java.lang.reflect.Method; - -/** - * SpringStatusChecker - */ -@Activate -public class SpringStatusChecker implements StatusChecker { - - private static final Logger logger = LoggerFactory.getLogger(SpringStatusChecker.class); - - @Override - public Status check() { - ApplicationContext context = null; - for (ApplicationContext c : SpringExtensionFactory.getContexts()) { - if (c != null) { - context = c; - break; - } - } - if (context == null) { - return new Status(Status.Level.UNKNOWN); - } - Status.Level level = Status.Level.OK; - if (context instanceof Lifecycle) { - if (((Lifecycle) context).isRunning()) { - level = Status.Level.OK; - } else { - level = Status.Level.ERROR; - } - } else { - level = Status.Level.UNKNOWN; - } - StringBuilder buf = new StringBuilder(); - try { - Class cls = context.getClass(); - Method method = null; - while (cls != null && method == null) { - try { - method = cls.getDeclaredMethod("getConfigLocations", new Class[0]); - } catch (NoSuchMethodException t) { - cls = cls.getSuperclass(); - } - } - if (method != null) { - if (!method.isAccessible()) { - method.setAccessible(true); - } - String[] configs = (String[]) method.invoke(context, new Object[0]); - if (configs != null && configs.length > 0) { - for (String config : configs) { - if (buf.length() > 0) { - buf.append(","); - } - buf.append(config); - } - } - } - } catch (Throwable t) { - logger.warn(t.getMessage(), t); - } - return new Status(level, buf.toString()); - } - -} +/* + * 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.status; + +import com.alibaba.dubbo.common.extension.Activate; +import com.alibaba.dubbo.common.logger.Logger; +import com.alibaba.dubbo.common.logger.LoggerFactory; +import com.alibaba.dubbo.common.status.Status; +import com.alibaba.dubbo.common.status.StatusChecker; +import com.alibaba.dubbo.config.spring.extension.SpringExtensionFactory; + +import org.springframework.context.ApplicationContext; +import org.springframework.context.Lifecycle; + +import java.lang.reflect.Method; + +/** + * SpringStatusChecker + */ +@Activate +public class SpringStatusChecker implements StatusChecker { + + private static final Logger logger = LoggerFactory.getLogger(SpringStatusChecker.class); + + @Override + public Status check() { + ApplicationContext context = null; + for (ApplicationContext c : SpringExtensionFactory.getContexts()) { + if (c != null) { + context = c; + break; + } + } + if (context == null) { + return new Status(Status.Level.UNKNOWN); + } + Status.Level level = Status.Level.OK; + if (context instanceof Lifecycle) { + if (((Lifecycle) context).isRunning()) { + level = Status.Level.OK; + } else { + level = Status.Level.ERROR; + } + } else { + level = Status.Level.UNKNOWN; + } + StringBuilder buf = new StringBuilder(); + try { + Class cls = context.getClass(); + Method method = null; + while (cls != null && method == null) { + try { + method = cls.getDeclaredMethod("getConfigLocations", new Class[0]); + } catch (NoSuchMethodException t) { + cls = cls.getSuperclass(); + } + } + if (method != null) { + if (!method.isAccessible()) { + method.setAccessible(true); + } + String[] configs = (String[]) method.invoke(context, new Object[0]); + if (configs != null && configs.length > 0) { + for (String config : configs) { + if (buf.length() > 0) { + buf.append(","); + } + buf.append(config); + } + } + } + } catch (Throwable t) { + logger.warn(t.getMessage(), t); + } + return new Status(level, buf.toString()); + } + +} diff --git a/dubbo-config/dubbo-config-spring/src/main/java/com/alibaba/dubbo/config/spring/util/AnnotatedBeanDefinitionRegistryUtils.java b/dubbo-config/dubbo-config-spring/src/main/java/com/alibaba/dubbo/config/spring/util/AnnotatedBeanDefinitionRegistryUtils.java new file mode 100644 index 00000000000..ccc34272a86 --- /dev/null +++ b/dubbo-config/dubbo-config-spring/src/main/java/com/alibaba/dubbo/config/spring/util/AnnotatedBeanDefinitionRegistryUtils.java @@ -0,0 +1,62 @@ +/* + * 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.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.springframework.beans.factory.config.BeanDefinition; +import org.springframework.beans.factory.support.BeanDefinitionRegistry; +import org.springframework.context.annotation.AnnotatedBeanDefinitionReader; +import org.springframework.util.ObjectUtils; + +import java.lang.annotation.Annotation; +import java.util.Arrays; + +/** + * Annotated {@link BeanDefinition} Utilities + *

+ * The source code is cloned from https://github.com/alibaba/spring-context-support/blob/1.0.2/src/main/java/com/alibaba/spring/util/AnnotatedBeanDefinitionRegistryUtils.java + * @since 2.6.6 + */ +public abstract class AnnotatedBeanDefinitionRegistryUtils { + + private static final Log logger = LogFactory.getLog(AnnotatedBeanDefinitionRegistryUtils.class); + + /** + * Register Beans + * + * @param registry {@link BeanDefinitionRegistry} + * @param annotatedClasses {@link Annotation annotation} class + */ + public static void registerBeans(BeanDefinitionRegistry registry, Class... annotatedClasses) { + + if (ObjectUtils.isEmpty(annotatedClasses)) { + return; + } + + boolean debugEnabled = logger.isDebugEnabled(); + + AnnotatedBeanDefinitionReader reader = new AnnotatedBeanDefinitionReader(registry); + + if (debugEnabled) { + logger.debug(registry.getClass().getSimpleName() + " will register annotated classes : " + Arrays.asList(annotatedClasses) + " ."); + } + + reader.register(annotatedClasses); + + } +} 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 index 7e5bb498d0b..703e649ad23 100644 --- 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 @@ -19,15 +19,39 @@ import com.alibaba.dubbo.config.annotation.Reference; import com.alibaba.dubbo.config.annotation.Service; +import org.springframework.core.env.Environment; +import org.springframework.core.env.PropertyResolver; import org.springframework.util.StringUtils; +import java.lang.annotation.Annotation; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; +import java.lang.reflect.Method; +import java.util.Collections; +import java.util.HashSet; +import java.util.LinkedHashMap; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import static java.lang.String.valueOf; +import static org.springframework.core.annotation.AnnotationUtils.findAnnotation; +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.trimWhitespace; + /** * Annotation Utilities Class * * @see org.springframework.core.annotation.AnnotationUtils * @since 2.5.11 */ -public class AnnotationUtils { +public abstract class AnnotationUtils { public static String resolveInterfaceName(Service service, Class defaultInterfaceClass) throws IllegalStateException { @@ -69,4 +93,192 @@ public static String resolveInterfaceName(Reference reference, Class defaultI } + + // Cloned from https://github.com/alibaba/spring-context-support/blob/1.0.2/src/main/java/com/alibaba/spring/util/AnnotationUtils.java + + /** + * Is specified {@link Annotation} present on {@link Method}'s declaring class or parameters or itself. + * + * @param method {@link Method} + * @param annotationClass {@link Annotation} type + * @param {@link Annotation} type + * @return If present , return true , or false + * @since 2.6.6 + */ + public static boolean isPresent(Method method, Class annotationClass) { + + Map> annotationsMap = findAnnotations(method, annotationClass); + + return !annotationsMap.isEmpty(); + + } + + /** + * Find specified {@link Annotation} type maps from {@link Method} + * + * @param method {@link Method} + * @param annotationClass {@link Annotation} type + * @param {@link Annotation} type + * @return {@link Annotation} type maps , the {@link ElementType} as key , + * the list of {@link Annotation} as value. + * If {@link Annotation} was annotated on {@link Method}'s parameters{@link ElementType#PARAMETER} , + * the associated {@link Annotation} list may contain multiple elements. + * @since 2.6.6 + */ + public static Map> findAnnotations(Method method, + Class annotationClass) { + + Retention retention = annotationClass.getAnnotation(Retention.class); + + RetentionPolicy retentionPolicy = retention.value(); + + if (!RetentionPolicy.RUNTIME.equals(retentionPolicy)) { + return Collections.emptyMap(); + } + + Map> annotationsMap = new LinkedHashMap>(); + + Target target = annotationClass.getAnnotation(Target.class); + + ElementType[] elementTypes = target.value(); + + + for (ElementType elementType : elementTypes) { + + List annotationsList = new LinkedList(); + + switch (elementType) { + + case PARAMETER: + + Annotation[][] parameterAnnotations = method.getParameterAnnotations(); + + for (Annotation[] annotations : parameterAnnotations) { + + for (Annotation annotation : annotations) { + + if (annotationClass.equals(annotation.annotationType())) { + + annotationsList.add((A) annotation); + + } + + } + + } + + break; + + case METHOD: + + A annotation = findAnnotation(method, annotationClass); + + if (annotation != null) { + + annotationsList.add(annotation); + + } + + break; + + case TYPE: + + Class beanType = method.getDeclaringClass(); + + A annotation2 = findAnnotation(beanType, annotationClass); + + if (annotation2 != null) { + + annotationsList.add(annotation2); + + } + + break; + + } + + if (!annotationsList.isEmpty()) { + + annotationsMap.put(elementType, annotationsList); + + } + + + } + + return Collections.unmodifiableMap(annotationsMap); + + } + + /** + * Get the {@link Annotation} attributes + * + * @param annotation specified {@link Annotation} + * @param ignoreDefaultValue whether ignore default value or not + * @param ignoreAttributeNames the attribute names of annotation should be ignored + * @return non-null + * @since 2.6.6 + */ + public static Map getAttributes(Annotation annotation, boolean ignoreDefaultValue, + String... ignoreAttributeNames) { + return getAttributes(annotation, null, ignoreDefaultValue, ignoreAttributeNames); + } + + /** + * Get the {@link Annotation} attributes + * + * @param annotation specified {@link Annotation} + * @param propertyResolver {@link PropertyResolver} instance, e.g {@link Environment} + * @param ignoreDefaultValue whether ignore default value or not + * @param ignoreAttributeNames the attribute names of annotation should be ignored + * @return non-null + * @since 2.6.6 + */ + public static Map getAttributes(Annotation annotation, PropertyResolver propertyResolver, + boolean ignoreDefaultValue, String... ignoreAttributeNames) { + + Set ignoreAttributeNamesSet = new HashSet(arrayToList(ignoreAttributeNames)); + + Map attributes = getAnnotationAttributes(annotation); + + Map actualAttributes = new LinkedHashMap(); + + for (Map.Entry 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 (attributeValue instanceof String) { + attributeValue = resolvePlaceholders(valueOf(attributeValue), propertyResolver); + } else if (attributeValue instanceof String[]) { + String[] values = (String[]) attributeValue; + for (int i = 0; i < values.length; i++) { + values[i] = resolvePlaceholders(values[i], propertyResolver); + } + attributeValue = values; + } + actualAttributes.put(attributeName, attributeValue); + } + return actualAttributes; + } + + private static String resolvePlaceholders(String attributeValue, PropertyResolver propertyResolver) { + String resolvedValue = attributeValue; + if (propertyResolver != null) { + resolvedValue = propertyResolver.resolvePlaceholders(resolvedValue); + resolvedValue = trimWhitespace(resolvedValue); + } + return resolvedValue; + } + } \ No newline at end of file diff --git a/dubbo-config/dubbo-config-spring/src/main/java/com/alibaba/dubbo/config/spring/util/BeanFactoryUtils.java b/dubbo-config/dubbo-config-spring/src/main/java/com/alibaba/dubbo/config/spring/util/BeanFactoryUtils.java index 13a3011c0d8..9018fddde5d 100644 --- a/dubbo-config/dubbo-config-spring/src/main/java/com/alibaba/dubbo/config/spring/util/BeanFactoryUtils.java +++ b/dubbo-config/dubbo-config-spring/src/main/java/com/alibaba/dubbo/config/spring/util/BeanFactoryUtils.java @@ -17,12 +17,21 @@ package com.alibaba.dubbo.config.spring.util; import org.springframework.beans.factory.BeanFactory; +import org.springframework.beans.factory.ListableBeanFactory; import org.springframework.beans.factory.config.ConfigurableBeanFactory; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationListener; import org.springframework.context.support.AbstractApplicationContext; import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Map; + +import static org.springframework.beans.factory.BeanFactoryUtils.beanNamesForTypeIncludingAncestors; +import static org.springframework.beans.factory.BeanFactoryUtils.beansOfTypeIncludingAncestors; +import static org.springframework.util.ObjectUtils.containsElement; /** * {@link BeanFactory} Utilities class @@ -31,7 +40,8 @@ * @see ConfigurableBeanFactory * @see org.springframework.beans.factory.BeanFactoryUtils */ -public class BeanFactoryUtils { +public abstract class BeanFactoryUtils { + public static boolean addApplicationListener(ApplicationContext applicationContext, ApplicationListener listener) { try { // backward compatibility to spring 2.0.1 @@ -55,4 +65,55 @@ public static boolean addApplicationListener(ApplicationContext applicationConte } return false; } + + /** + * Get optional Bean + * + * @param beanFactory {@link ListableBeanFactory} + * @param beanName the name of Bean + * @param beanType the {@link Class type} of Bean + * @param the {@link Class type} of Bean + * @return A bean if present , or null + * @since 2.6.6 + */ + public static T getOptionalBean(ListableBeanFactory beanFactory, String beanName, Class beanType) { + + String[] allBeanNames = beanNamesForTypeIncludingAncestors(beanFactory, beanType); + + if (!containsElement(allBeanNames, beanName)) { + return null; + } + + Map beansOfType = beansOfTypeIncludingAncestors(beanFactory, beanType); + + return beansOfType.get(beanName); + + } + + + /** + * Gets name-matched Beans from {@link ListableBeanFactory BeanFactory} + * + * @param beanFactory {@link ListableBeanFactory BeanFactory} + * @param beanNames the names of Bean + * @param beanType the {@link Class type} of Bean + * @param the {@link Class type} of Bean + * @return the read-only and non-null {@link List} of Bean names + * @since 2.6.6 + */ + public static List getBeans(ListableBeanFactory beanFactory, String[] beanNames, Class beanType) { + + String[] allBeanNames = beanNamesForTypeIncludingAncestors(beanFactory, beanType); + + List beans = new ArrayList(beanNames.length); + + for (String beanName : beanNames) { + if (containsElement(allBeanNames, beanName)) { + beans.add(beanFactory.getBean(beanName, beanType)); + } + } + + return Collections.unmodifiableList(beans); + } + } diff --git a/dubbo-config/dubbo-config-spring/src/main/java/com/alibaba/dubbo/config/spring/util/BeanRegistrar.java b/dubbo-config/dubbo-config-spring/src/main/java/com/alibaba/dubbo/config/spring/util/BeanRegistrar.java index 671d63f277b..08a13acaa66 100644 --- a/dubbo-config/dubbo-config-spring/src/main/java/com/alibaba/dubbo/config/spring/util/BeanRegistrar.java +++ b/dubbo-config/dubbo-config-spring/src/main/java/com/alibaba/dubbo/config/spring/util/BeanRegistrar.java @@ -25,7 +25,7 @@ * * @since 2.5.7 */ -public class BeanRegistrar { +public abstract class BeanRegistrar { /** * Register Infrastructure Bean diff --git a/dubbo-config/dubbo-config-spring/src/main/java/com/alibaba/dubbo/config/spring/util/ClassUtils.java b/dubbo-config/dubbo-config-spring/src/main/java/com/alibaba/dubbo/config/spring/util/ClassUtils.java new file mode 100644 index 00000000000..6bb1d81d417 --- /dev/null +++ b/dubbo-config/dubbo-config-spring/src/main/java/com/alibaba/dubbo/config/spring/util/ClassUtils.java @@ -0,0 +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.util; + +import java.lang.reflect.ParameterizedType; +import java.lang.reflect.Type; + +/** + * {@link Class} Utilities + *

+ * The source code is cloned from + * https://github.com/alibaba/spring-context-support/blob/1.0.2/src/main/java/com/alibaba/spring/util/ClassUtils.java + * + * @since 2.6.6 + */ +public abstract class ClassUtils { + + public static Class resolveGenericType(Class declaredClass) { + ParameterizedType parameterizedType = (ParameterizedType) declaredClass.getGenericSuperclass(); + Type[] actualTypeArguments = parameterizedType.getActualTypeArguments(); + return (Class) actualTypeArguments[0]; + } +} diff --git a/dubbo-config/dubbo-config-spring/src/main/java/com/alibaba/dubbo/config/spring/util/ObjectUtils.java b/dubbo-config/dubbo-config-spring/src/main/java/com/alibaba/dubbo/config/spring/util/ObjectUtils.java new file mode 100644 index 00000000000..abb981febd1 --- /dev/null +++ b/dubbo-config/dubbo-config-spring/src/main/java/com/alibaba/dubbo/config/spring/util/ObjectUtils.java @@ -0,0 +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.util; + +/** + * Object Utilities + * + * @since 2.6.6 + */ +public abstract class ObjectUtils { + + /** + * Convert from variable arguments to array + * + * @param values variable arguments + * @param The class + * @return array + */ + public static 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 new file mode 100644 index 00000000000..06c707781d7 --- /dev/null +++ b/dubbo-config/dubbo-config-spring/src/main/java/com/alibaba/dubbo/config/spring/util/PropertySourcesUtils.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 com.alibaba.dubbo.config.spring.util; + +import org.springframework.core.env.AbstractEnvironment; +import org.springframework.core.env.ConfigurableEnvironment; +import org.springframework.core.env.EnumerablePropertySource; +import org.springframework.core.env.MutablePropertySources; +import org.springframework.core.env.PropertySource; +import org.springframework.core.env.PropertySources; + +import java.util.Collections; +import java.util.LinkedHashMap; +import java.util.Map; +import java.util.Properties; + + +/** + * {@link PropertySources} Utilities + *

+ * The source code is cloned from https://github.com/alibaba/spring-context-support/blob/1.0.2/src/main/java/com/alibaba/spring/util/PropertySourcesUtils.java + * + * @since 2.6.6 + */ +public abstract class PropertySourcesUtils { + + /** + * Get Sub {@link Properties} + * + * @param propertySources {@link PropertySource} Iterable + * @param prefix the prefix of property name + * @return Map + * @see Properties + */ + public static Map getSubProperties(Iterable> propertySources, String prefix) { + + // Non-Extension AbstractEnvironment + AbstractEnvironment environment = new AbstractEnvironment() { + }; + + MutablePropertySources mutablePropertySources = environment.getPropertySources(); + + for (PropertySource source : propertySources) { + mutablePropertySources.addLast(source); + } + + return getSubProperties(environment, prefix); + + } + + /** + * Get Sub {@link Properties} + * + * @param environment {@link ConfigurableEnvironment} + * @param prefix the prefix of property name + * @return Map + * @see Properties + */ + public static Map getSubProperties(ConfigurableEnvironment environment, String prefix) { + + Map subProperties = new LinkedHashMap(); + + MutablePropertySources propertySources = environment.getPropertySources(); + + String normalizedPrefix = normalizePrefix(prefix); + + for (PropertySource source : propertySources) { + if (source instanceof EnumerablePropertySource) { + for (String name : ((EnumerablePropertySource) source).getPropertyNames()) { + if (!subProperties.containsKey(name) && name.startsWith(normalizedPrefix)) { + String subName = name.substring(normalizedPrefix.length()); + if (!subProperties.containsKey(subName)) { // take first one + Object value = source.getProperty(name); + if (value instanceof String) { + // Resolve placeholder + value = environment.resolvePlaceholders((String) value); + } + subProperties.put(subName, value); + } + } + } + } + } + + return Collections.unmodifiableMap(subProperties); + + } + + /** + * 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/util/AnnotatedBeanDefinitionRegistryUtilsTest.java b/dubbo-config/dubbo-config-spring/src/test/java/com/alibaba/dubbo/config/spring/util/AnnotatedBeanDefinitionRegistryUtilsTest.java new file mode 100644 index 00000000000..c54fa9feb8a --- /dev/null +++ b/dubbo-config/dubbo-config-spring/src/test/java/com/alibaba/dubbo/config/spring/util/AnnotatedBeanDefinitionRegistryUtilsTest.java @@ -0,0 +1,59 @@ +/* + * 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.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.springframework.beans.factory.support.DefaultListableBeanFactory; +import org.springframework.context.annotation.AnnotationConfigUtils; +import org.springframework.util.ObjectUtils; + +/** + * {@link AnnotatedBeanDefinitionRegistryUtils} Test + * + * @see AnnotatedBeanDefinitionRegistryUtils + * @since 2.6.6 + */ +public class AnnotatedBeanDefinitionRegistryUtilsTest { + + private DefaultListableBeanFactory registry = null; + + @Before + public void init() { + registry = new DefaultListableBeanFactory(); + AnnotationConfigUtils.registerAnnotationConfigProcessors(registry); + } + + @Test + public void testRegisterBeans() { + + AnnotatedBeanDefinitionRegistryUtils.registerBeans(registry, this.getClass()); + + String[] beanNames = registry.getBeanNamesForType(this.getClass()); + + Assert.assertEquals(1, beanNames.length); + + beanNames = registry.getBeanNamesForType(AnnotatedBeanDefinitionRegistryUtils.class); + + Assert.assertTrue(ObjectUtils.isEmpty(beanNames)); + + AnnotatedBeanDefinitionRegistryUtils.registerBeans(registry); + + } + +} diff --git a/dubbo-config/dubbo-config-spring/src/test/java/com/alibaba/dubbo/config/spring/util/PropertySourcesUtilsTest.java b/dubbo-config/dubbo-config-spring/src/test/java/com/alibaba/dubbo/config/spring/util/PropertySourcesUtilsTest.java new file mode 100644 index 00000000000..4a17ac1c7b2 --- /dev/null +++ b/dubbo-config/dubbo-config-spring/src/test/java/com/alibaba/dubbo/config/spring/util/PropertySourcesUtilsTest.java @@ -0,0 +1,80 @@ +/* + * 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.junit.Assert; +import org.junit.Test; +import org.springframework.core.env.MapPropertySource; +import org.springframework.core.env.MutablePropertySources; + +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; + +/** + * {@link PropertySourcesUtils} Test + * + * @author Mercy + * @see PropertySourcesUtils + * @since 2.6.6 + */ +public class PropertySourcesUtilsTest { + + @Test + public void testGetSubProperties() { + + MutablePropertySources propertySources = new MutablePropertySources(); + + Map source = new HashMap(); + Map source2 = new HashMap(); + + MapPropertySource propertySource = new MapPropertySource("propertySource", source); + MapPropertySource propertySource2 = new MapPropertySource("propertySource2", source2); + + propertySources.addLast(propertySource); + propertySources.addLast(propertySource2); + + Map result = PropertySourcesUtils.getSubProperties(propertySources, "user"); + + Assert.assertEquals(Collections.emptyMap(), result); + + source.put("age", "31"); + source.put("user.name", "Mercy"); + source.put("user.age", "${age}"); + + source2.put("user.name", "mercyblitz"); + source2.put("user.age", "32"); + + Map expected = new HashMap(); + expected.put("name", "Mercy"); + expected.put("age", "31"); + + result = PropertySourcesUtils.getSubProperties(propertySources, "user"); + + Assert.assertEquals(expected, result); + + result = PropertySourcesUtils.getSubProperties(propertySources, ""); + + Assert.assertEquals(Collections.emptyMap(), result); + + result = PropertySourcesUtils.getSubProperties(propertySources, "no-exists"); + + Assert.assertEquals(Collections.emptyMap(), result); + + } + +}