diff --git a/dependencies-bom/pom.xml b/dependencies-bom/pom.xml
index 752816b0cbe..e6bda8f0c45 100644
--- a/dependencies-bom/pom.xml
+++ b/dependencies-bom/pom.xml
@@ -112,6 +112,7 @@
2.2.7
1.2.0
3.2.4
+ 1.0.1
@@ -358,6 +359,16 @@
hessian-lite
${hessian_lite_version}
+
+
+
+
+
+ com.alibaba.spring
+ spring-context-support
+ ${alibaba_spring_context_support_version}
+
+
org.apache.curator
diff --git a/dubbo-config/dubbo-config-spring/pom.xml b/dubbo-config/dubbo-config-spring/pom.xml
index ad3ea15a13b..8978c488c93 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
@@ -51,6 +52,10 @@
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/ServiceBean.java b/dubbo-config/dubbo-config-spring/src/main/java/com/alibaba/dubbo/config/spring/ServiceBean.java
index b38684b2c75..6174d1b752d 100644
--- a/dubbo-config/dubbo-config-spring/src/main/java/com/alibaba/dubbo/config/spring/ServiceBean.java
+++ b/dubbo-config/dubbo-config-spring/src/main/java/com/alibaba/dubbo/config/spring/ServiceBean.java
@@ -24,7 +24,9 @@
import com.alibaba.dubbo.config.RegistryConfig;
import com.alibaba.dubbo.config.ServiceConfig;
import com.alibaba.dubbo.config.annotation.Service;
+import com.alibaba.dubbo.config.spring.context.event.ServiceBeanExportedEvent;
import com.alibaba.dubbo.config.spring.extension.SpringExtensionFactory;
+
import org.springframework.aop.support.AopUtils;
import org.springframework.beans.factory.BeanFactoryUtils;
import org.springframework.beans.factory.BeanNameAware;
@@ -32,6 +34,8 @@
import org.springframework.beans.factory.InitializingBean;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
+import org.springframework.context.ApplicationEventPublisher;
+import org.springframework.context.ApplicationEventPublisherAware;
import org.springframework.context.ApplicationListener;
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.context.support.AbstractApplicationContext;
@@ -46,7 +50,9 @@
*
* @export
*/
-public class ServiceBean extends ServiceConfig implements InitializingBean, DisposableBean, ApplicationContextAware, ApplicationListener, BeanNameAware {
+public class ServiceBean extends ServiceConfig implements InitializingBean, DisposableBean,
+ ApplicationContextAware, ApplicationListener, BeanNameAware,
+ ApplicationEventPublisherAware {
private static final long serialVersionUID = 213195494150089726L;
@@ -60,6 +66,8 @@ public class ServiceBean extends ServiceConfig implements InitializingBean
private transient boolean supportedApplicationListener;
+ private ApplicationEventPublisher applicationEventPublisher;
+
public ServiceBean() {
super();
this.service = null;
@@ -265,6 +273,34 @@ && getInterface() != null && getInterface().length() > 0
}
}
+ /**
+ * Get the name of {@link ServiceBean}
+ *
+ * @return {@link ServiceBean}'s name
+ * @since 2.6.5
+ */
+ public String getBeanName() {
+ return this.beanName;
+ }
+
+ /**
+ * @since 2.6.5
+ */
+ @Override
+ public void export() {
+ super.export();
+ // Publish ServiceBeanExportedEvent
+ publishExportEvent();
+ }
+
+ /**
+ * @since 2.6.5
+ */
+ private void publishExportEvent() {
+ ServiceBeanExportedEvent exportEvent = new ServiceBeanExportedEvent(this);
+ applicationEventPublisher.publishEvent(exportEvent);
+ }
+
@Override
public void destroy() throws Exception {
// This will only be called for singleton scope bean, and expected to be called by spring shutdown hook when BeanFactory/ApplicationContext destroys.
@@ -280,4 +316,13 @@ protected Class getServiceClass(T ref) {
}
return super.getServiceClass(ref);
}
+
+ /**
+ * @param applicationEventPublisher
+ * @since 2.6.5
+ */
+ @Override
+ public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) {
+ this.applicationEventPublisher = applicationEventPublisher;
+ }
}
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 fc8d3f46105..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
@@ -21,6 +21,7 @@
import com.alibaba.dubbo.config.ModuleConfig;
import com.alibaba.dubbo.config.MonitorConfig;
import com.alibaba.dubbo.config.RegistryConfig;
+
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.context.ApplicationContext;
@@ -34,6 +35,7 @@
/**
* Abstract Configurable {@link Annotation} Bean Builder
+ *
* @since 2.5.7
*/
abstract class AbstractAnnotationConfigBeanBuilder {
@@ -76,7 +78,7 @@ public final B build() throws Exception {
configureBean(bean);
if (logger.isInfoEnabled()) {
- logger.info(bean + " has been built.");
+ logger.info("The bean[type:" + bean.getClass().getSimpleName() + "] has been built.");
}
return bean;
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 cfd719668ae..2e45c692c0f 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
@@ -18,488 +18,236 @@
import com.alibaba.dubbo.config.annotation.Reference;
import com.alibaba.dubbo.config.spring.ReferenceBean;
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.springframework.beans.BeanUtils;
+import com.alibaba.dubbo.config.spring.ServiceBean;
+import com.alibaba.dubbo.config.spring.context.event.ServiceBeanExportedEvent;
+import com.alibaba.dubbo.config.spring.util.AnnotationUtils;
+import com.alibaba.spring.beans.factory.annotation.AnnotationInjectedBeanPostProcessor;
+
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.DisposableBean;
import org.springframework.beans.factory.annotation.InjectionMetadata;
-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.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;
+import org.springframework.context.ApplicationEvent;
+import org.springframework.context.ApplicationListener;
+import org.springframework.context.event.ContextRefreshedEvent;
-import java.beans.PropertyDescriptor;
import java.lang.reflect.Field;
+import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
-import java.lang.reflect.Modifier;
-import java.util.ArrayList;
+import java.lang.reflect.Proxy;
import java.util.Collection;
-import java.util.LinkedHashMap;
-import java.util.LinkedList;
-import java.util.List;
+import java.util.Collections;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
-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;
-
/**
* {@link org.springframework.beans.factory.config.BeanPostProcessor} implementation
* that Consumer service {@link Reference} annotated fields
*
* @since 2.5.7
*/
-public class ReferenceAnnotationBeanPostProcessor extends InstantiationAwareBeanPostProcessorAdapter
- implements MergedBeanDefinitionPostProcessor, PriorityOrdered, ApplicationContextAware, BeanClassLoaderAware,
- DisposableBean {
+public class ReferenceAnnotationBeanPostProcessor extends AnnotationInjectedBeanPostProcessor
+ implements ApplicationContextAware, ApplicationListener {
/**
* The bean name of {@link ReferenceAnnotationBeanPostProcessor}
*/
public static final String BEAN_NAME = "referenceAnnotationBeanPostProcessor";
- private final Log logger = LogFactory.getLog(getClass());
+ /**
+ * Cache size
+ */
+ private static final int CACHE_SIZE = Integer.getInteger(BEAN_NAME + ".cache.size", 32);
- private ApplicationContext applicationContext;
+ private final ConcurrentMap> referenceBeanCache =
+ new ConcurrentHashMap>(CACHE_SIZE);
- private ClassLoader classLoader;
+ private final ConcurrentHashMap localReferenceBeanInvocationHandlerCache =
+ new ConcurrentHashMap(CACHE_SIZE);
- private final ConcurrentMap injectionMetadataCache =
- new ConcurrentHashMap(256);
+ private final ConcurrentMap> injectedFieldReferenceBeanCache =
+ new ConcurrentHashMap>(CACHE_SIZE);
- private final ConcurrentMap> referenceBeansCache =
- new ConcurrentHashMap>();
-
- @Override
- public PropertyValues postProcessPropertyValues(
- PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeanCreationException {
-
- InjectionMetadata metadata = findReferenceMetadata(beanName, bean.getClass(), pvs);
- try {
- metadata.inject(bean, beanName, pvs);
- } catch (BeanCreationException ex) {
- throw ex;
- } catch (Throwable ex) {
- throw new BeanCreationException(beanName, "Injection of @Reference dependencies failed", ex);
- }
- return pvs;
- }
+ private final ConcurrentMap> injectedMethodReferenceBeanCache =
+ new ConcurrentHashMap>(CACHE_SIZE);
+ private ApplicationContext applicationContext;
/**
- * Finds {@link InjectionMetadata.InjectedElement} Metadata from annotated {@link Reference @Reference} fields
+ * Gets all beans of {@link ReferenceBean}
*
- * @param beanClass The {@link Class} of Bean
- * @return non-null {@link List}
+ * @return non-null read-only {@link Collection}
+ * @since 2.5.9
*/
- private List findFieldReferenceMetadata(final Class> beanClass) {
-
- final List elements = new LinkedList();
-
- ReflectionUtils.doWithFields(beanClass, new ReflectionUtils.FieldCallback() {
- @Override
- public void doWith(Field field) throws IllegalArgumentException, IllegalAccessException {
-
- Reference reference = getAnnotation(field, Reference.class);
-
- if (reference != null) {
-
- if (Modifier.isStatic(field.getModifiers())) {
- if (logger.isWarnEnabled()) {
- logger.warn("@Reference annotation is not supported on static fields: " + field);
- }
- return;
- }
-
- elements.add(new ReferenceFieldElement(field, reference));
- }
-
- }
- });
-
- return elements;
-
+ public Collection> getReferenceBeans() {
+ return referenceBeanCache.values();
}
/**
- * Finds {@link InjectionMetadata.InjectedElement} Metadata from annotated {@link Reference @Reference} methods
+ * Get {@link ReferenceBean} {@link Map} in injected field.
*
- * @param beanClass The {@link Class} of Bean
- * @return non-null {@link List}
+ * @return non-null {@link Map}
+ * @since 2.5.11
*/
- private List findMethodReferenceMetadata(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;
- }
-
- Reference reference = findAnnotation(bridgedMethod, Reference.class);
-
- if (reference != null && method.equals(ClassUtils.getMostSpecificMethod(method, beanClass))) {
- if (Modifier.isStatic(method.getModifiers())) {
- if (logger.isWarnEnabled()) {
- logger.warn("@Reference annotation is not supported on static methods: " + method);
- }
- return;
- }
- if (method.getParameterTypes().length == 0) {
- if (logger.isWarnEnabled()) {
- logger.warn("@Reference annotation should only be used on methods with parameters: " +
- method);
- }
- }
- PropertyDescriptor pd = BeanUtils.findPropertyForMethod(bridgedMethod, beanClass);
- elements.add(new ReferenceMethodElement(method, pd, reference));
- }
- }
- });
-
- return elements;
-
+ public Map> getInjectedFieldReferenceBeanMap() {
+ return Collections.unmodifiableMap(injectedFieldReferenceBeanCache);
}
-
/**
- * @param beanClass
- * @return
+ * Get {@link ReferenceBean} {@link Map} in injected method.
+ *
+ * @return non-null {@link Map}
+ * @since 2.5.11
*/
- private ReferenceInjectionMetadata buildReferenceMetadata(final Class> beanClass) {
- Collection fieldElements = findFieldReferenceMetadata(beanClass);
- Collection methodElements = findMethodReferenceMetadata(beanClass);
- return new ReferenceInjectionMetadata(beanClass, fieldElements, methodElements);
-
- }
-
- private InjectionMetadata findReferenceMetadata(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.
- ReferenceInjectionMetadata 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 = buildReferenceMetadata(clazz);
- this.injectionMetadataCache.put(cacheKey, metadata);
- } catch (NoClassDefFoundError err) {
- throw new IllegalStateException("Failed to introspect bean class [" + clazz.getName() +
- "] for reference metadata: could not find class that it depends on", err);
- }
- }
- }
- }
- return metadata;
- }
-
- @Override
- public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
- this.applicationContext = applicationContext;
- }
-
- @Override
- public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class> beanType, String beanName) {
- if (beanType != null) {
- InjectionMetadata metadata = findReferenceMetadata(beanName, beanType, null);
- metadata.checkConfigMembers(beanDefinition);
- }
- }
-
- @Override
- public int getOrder() {
- return LOWEST_PRECEDENCE;
+ public Map> getInjectedMethodReferenceBeanMap() {
+ return Collections.unmodifiableMap(injectedMethodReferenceBeanCache);
}
@Override
- public void destroy() throws Exception {
+ protected Object doGetInjectedBean(Reference reference, Object bean, String beanName, Class> injectedType,
+ InjectionMetadata.InjectedElement injectedElement) throws Exception {
- for (ReferenceBean referenceBean : referenceBeansCache.values()) {
- if (logger.isInfoEnabled()) {
- logger.info(referenceBean + " was destroying!");
- }
- referenceBean.destroy();
- }
+ String referencedBeanName = buildReferencedBeanName(reference, injectedType);
- injectionMetadataCache.clear();
- referenceBeansCache.clear();
+ ReferenceBean referenceBean = buildReferenceBeanIfAbsent(referencedBeanName, reference, injectedType, getClassLoader());
- if (logger.isInfoEnabled()) {
- logger.info(getClass() + " was destroying!");
- }
+ cacheInjectedReferenceBean(referenceBean, injectedElement);
- }
+ Object proxy = buildProxy(referencedBeanName, referenceBean, injectedType);
- @Override
- public void setBeanClassLoader(ClassLoader classLoader) {
- this.classLoader = classLoader;
+ return proxy;
}
-
- /**
- * Gets all beans of {@link ReferenceBean}
- *
- * @return non-null {@link Collection}
- * @since 2.5.9
- */
- public Collection> getReferenceBeans() {
- return this.referenceBeansCache.values();
+ private Object buildProxy(String referencedBeanName, ReferenceBean referenceBean, Class> injectedType) {
+ InvocationHandler handler = buildInvocationHandler(referencedBeanName, referenceBean);
+ Object proxy = Proxy.newProxyInstance(getClassLoader(), new Class[]{injectedType}, handler);
+ return proxy;
}
+ private InvocationHandler buildInvocationHandler(String referencedBeanName, ReferenceBean referenceBean) {
- /**
- * {@link Reference} {@link InjectionMetadata} implementation
- *
- * @since 2.5.11
- */
- private static class ReferenceInjectionMetadata extends InjectionMetadata {
-
- private final Collection fieldElements;
+ ReferenceBeanInvocationHandler handler = localReferenceBeanInvocationHandlerCache.get(referencedBeanName);
- private final Collection methodElements;
-
-
- public ReferenceInjectionMetadata(Class> targetClass, Collection fieldElements,
- Collection methodElements) {
- super(targetClass, combine(fieldElements, methodElements));
- this.fieldElements = fieldElements;
- this.methodElements = methodElements;
+ if (handler == null) {
+ handler = new ReferenceBeanInvocationHandler(referenceBean);
}
- private static Collection combine(Collection extends T>... elements) {
- List allElements = new ArrayList();
- for (Collection extends T> e : elements) {
- allElements.addAll(e);
- }
- return allElements;
- }
-
- public Collection getFieldElements() {
- return fieldElements;
+ if (applicationContext.containsBean(referencedBeanName)) { // Is local @Service Bean or not ?
+ // ReferenceBeanInvocationHandler's initialization has to wait for current local @Service Bean has been exported.
+ localReferenceBeanInvocationHandlerCache.put(referencedBeanName, handler);
+ } else {
+ // Remote Reference Bean should initialize immediately
+ handler.init();
}
- public Collection getMethodElements() {
- return methodElements;
- }
+ return handler;
}
- /**
- * {@link Reference} {@link Method} {@link InjectionMetadata.InjectedElement}
- */
- private class ReferenceMethodElement extends InjectionMetadata.InjectedElement {
+ private static class ReferenceBeanInvocationHandler implements InvocationHandler {
- private final Method method;
+ private final ReferenceBean referenceBean;
- private final Reference reference;
+ private Object bean;
- private volatile ReferenceBean> referenceBean;
-
- protected ReferenceMethodElement(Method method, PropertyDescriptor pd, Reference reference) {
- super(method, pd);
- this.method = method;
- this.reference = reference;
+ private ReferenceBeanInvocationHandler(ReferenceBean referenceBean) {
+ this.referenceBean = referenceBean;
}
@Override
- protected void inject(Object bean, String beanName, PropertyValues pvs) throws Throwable {
-
- Class> referenceClass = pd.getPropertyType();
-
- referenceBean = buildReferenceBean(reference, referenceClass);
-
- ReflectionUtils.makeAccessible(method);
-
- method.invoke(bean, referenceBean.getObject());
-
+ public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
+ return method.invoke(bean, args);
}
- }
-
- /**
- * {@link Reference} {@link Field} {@link InjectionMetadata.InjectedElement}
- */
- private class ReferenceFieldElement extends InjectionMetadata.InjectedElement {
-
- private final Field field;
-
- private final Reference reference;
-
- private volatile ReferenceBean> referenceBean;
-
- protected ReferenceFieldElement(Field field, Reference reference) {
- super(field, null);
- this.field = field;
- this.reference = reference;
+ private void init() {
+ this.bean = referenceBean.get();
}
+ }
- @Override
- protected void inject(Object bean, String beanName, PropertyValues pvs) throws Throwable {
-
- Class> referenceClass = field.getType();
+ @Override
+ protected String buildInjectedObjectCacheKey(Reference reference, Object bean, String beanName,
+ Class> injectedType, InjectionMetadata.InjectedElement injectedElement) {
- referenceBean = buildReferenceBean(reference, referenceClass);
+ String key = buildReferencedBeanName(reference, injectedType) +
+ "#source=" + (injectedElement.getMember()) +
+ "#attributes=" + AnnotationUtils.getAttributes(reference,getEnvironment(),true);
- ReflectionUtils.makeAccessible(field);
+ return key;
+ }
- field.set(bean, referenceBean.getObject());
+ private String buildReferencedBeanName(Reference reference, Class> injectedType) {
- }
+ ServiceBeanNameBuilder builder = ServiceBeanNameBuilder.create(reference, injectedType, getEnvironment());
+ return getEnvironment().resolvePlaceholders(builder.build());
}
- private ReferenceBean> buildReferenceBean(Reference reference, Class> referenceClass) throws Exception {
-
- String referenceBeanCacheKey = generateReferenceBeanCacheKey(reference, referenceClass);
+ private ReferenceBean buildReferenceBeanIfAbsent(String referencedBeanName, Reference reference,
+ Class> referencedType, ClassLoader classLoader)
+ throws Exception {
- ReferenceBean> referenceBean = referenceBeansCache.get(referenceBeanCacheKey);
+ ReferenceBean> referenceBean = referenceBeanCache.get(referencedBeanName);
if (referenceBean == null) {
-
ReferenceBeanBuilder beanBuilder = ReferenceBeanBuilder
.create(reference, classLoader, applicationContext)
- .interfaceClass(referenceClass);
-
+ .interfaceClass(referencedType);
referenceBean = beanBuilder.build();
-
- referenceBeansCache.putIfAbsent(referenceBeanCacheKey, referenceBean);
-
+ referenceBeanCache.put(referencedBeanName, referenceBean);
}
return referenceBean;
-
}
-
- /**
- * Generate a cache key of {@link ReferenceBean}
- *
- * @param reference {@link Reference}
- * @param beanClass {@link Class}
- * @return
- */
- private String generateReferenceBeanCacheKey(Reference reference, Class> beanClass) {
-
- String interfaceName = resolveInterfaceName(reference, beanClass);
-
- String key = reference.url() + "/" + interfaceName +
- "/" + reference.version() +
- "/" + reference.group();
-
- Environment environment = applicationContext.getEnvironment();
-
- key = environment.resolvePlaceholders(key);
-
- return key;
-
- }
-
- private static String resolveInterfaceName(Reference reference, Class> beanClass)
- throws IllegalStateException {
-
- String interfaceName;
- if (!"".equals(reference.interfaceName())) {
- interfaceName = reference.interfaceName();
- } else if (!void.class.equals(reference.interfaceClass())) {
- interfaceName = reference.interfaceClass().getName();
- } else if (beanClass.isInterface()) {
- interfaceName = beanClass.getName();
- } else {
- throw new IllegalStateException(
- "The @Reference undefined interfaceClass or interfaceName, and the property type "
- + beanClass.getName() + " is not a interface.");
+ private void cacheInjectedReferenceBean(ReferenceBean referenceBean,
+ InjectionMetadata.InjectedElement injectedElement) {
+ if (injectedElement.getMember() instanceof Field) {
+ injectedFieldReferenceBeanCache.put(injectedElement, referenceBean);
+ } else if (injectedElement.getMember() instanceof Method) {
+ injectedMethodReferenceBeanCache.put(injectedElement, referenceBean);
}
-
- return interfaceName;
-
}
+ @Override
+ public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
+ this.applicationContext = applicationContext;
+ }
- /**
- * Get {@link ReferenceBean} {@link Map} in injected field.
- *
- * @return non-null {@link Map}
- * @since 2.5.11
- */
- public Map> getInjectedFieldReferenceBeanMap() {
-
- Map> injectedElementReferenceBeanMap =
- new LinkedHashMap>();
-
- for (ReferenceInjectionMetadata metadata : injectionMetadataCache.values()) {
-
- Collection fieldElements = metadata.getFieldElements();
-
- for (ReferenceFieldElement fieldElement : fieldElements) {
-
- injectedElementReferenceBeanMap.put(fieldElement, fieldElement.referenceBean);
-
- }
-
+ @Override
+ public void onApplicationEvent(ApplicationEvent event) {
+ if (event instanceof ServiceBeanExportedEvent) {
+ onServiceBeanExportEvent((ServiceBeanExportedEvent) event);
+ } else if (event instanceof ContextRefreshedEvent) {
+ onContextRefreshedEvent((ContextRefreshedEvent) event);
}
-
- return injectedElementReferenceBeanMap;
-
}
- /**
- * Get {@link ReferenceBean} {@link Map} in injected method.
- *
- * @return non-null {@link Map}
- * @since 2.5.11
- */
- public Map> getInjectedMethodReferenceBeanMap() {
-
- Map> injectedElementReferenceBeanMap =
- new LinkedHashMap>();
-
- for (ReferenceInjectionMetadata metadata : injectionMetadataCache.values()) {
-
- Collection methodElements = metadata.getMethodElements();
-
- for (ReferenceMethodElement methodElement : methodElements) {
-
- injectedElementReferenceBeanMap.put(methodElement, methodElement.referenceBean);
-
- }
+ private void onServiceBeanExportEvent(ServiceBeanExportedEvent event) {
+ ServiceBean serviceBean = event.getServiceBean();
+ initReferenceBeanInvocationHandler(serviceBean);
+ }
+ private void initReferenceBeanInvocationHandler(ServiceBean serviceBean) {
+ String serviceBeanName = serviceBean.getBeanName();
+ // Remove ServiceBean when it's exported
+ ReferenceBeanInvocationHandler handler = localReferenceBeanInvocationHandlerCache.remove(serviceBeanName);
+ // Initialize
+ if (handler != null) {
+ handler.init();
}
-
- return injectedElementReferenceBeanMap;
-
}
- private T getFieldValue(Object object, String fieldName, Class fieldType) {
-
- Field field = ReflectionUtils.findField(object.getClass(), fieldName, fieldType);
-
- ReflectionUtils.makeAccessible(field);
-
- return (T) ReflectionUtils.getField(field, object);
+ private void onContextRefreshedEvent(ContextRefreshedEvent event) {
}
-}
+ @Override
+ public void destroy() throws Exception {
+ super.destroy();
+ this.referenceBeanCache.clear();
+ this.localReferenceBeanInvocationHandlerCache.clear();
+ this.injectedFieldReferenceBeanCache.clear();
+ this.injectedMethodReferenceBeanCache.clear();
+ }
+}
\ No newline at end of file
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 5d9418fbc8a..883a56a1879 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
@@ -16,21 +16,23 @@
*/
package com.alibaba.dubbo.config.spring.beans.factory.annotation;
+import com.alibaba.dubbo.common.utils.CollectionUtils;
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.beans.propertyeditors.StringTrimmerEditor;
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 java.beans.PropertyEditorSupport;
+import java.util.Map;
+
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;
/**
* {@link ReferenceBean} Builder
@@ -39,6 +41,8 @@
*/
class ReferenceBeanBuilder extends AbstractAnnotationConfigBeanBuilder {
+ // Ignore those fields
+ static final String[] IGNORE_FIELD_NAMES = of("application", "module", "consumer", "monitor", "registry");
private ReferenceBeanBuilder(Reference annotation, ClassLoader classLoader, ApplicationContext applicationContext) {
super(annotation, classLoader, applicationContext);
@@ -93,20 +97,30 @@ protected ReferenceBean doBuild() {
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);
+ // Register CustomEditors for special fields
+ dataBinder.registerCustomEditor(String.class, "filter", new StringTrimmerEditor(true));
+ dataBinder.registerCustomEditor(String.class, "listener", new StringTrimmerEditor(true));
+ dataBinder.registerCustomEditor(Map.class, "parameters", new PropertyEditorSupport() {
+
+ public void setAsText(String text) throws java.lang.IllegalArgumentException {
+ // Trim all whitespace
+ String content = StringUtils.trimAllWhitespace(text);
+ if (!StringUtils.hasText(content)) { // No content , ignore directly
+ return;
+ }
+ // replace "=" to ","
+ content = StringUtils.replace(content, "=", ",");
+ // replace ":" to ","
+ content = StringUtils.replace(content, ":", ",");
+ // String[] to Map
+ Map parameters = CollectionUtils.toStringMap(commaDelimitedListToStringArray(content));
+ setValue(parameters);
+ }
+ });
+
// Bind annotation attributes
- dataBinder.bind(new AnnotationPropertyValuesAdapter(reference, applicationContext.getEnvironment(), ignoreAttributeNames));
- }
+ dataBinder.bind(new AnnotationPropertyValuesAdapter(reference, applicationContext.getEnvironment(), IGNORE_FIELD_NAMES));
- private ConversionService getConversionService() {
- DefaultConversionService conversionService = new DefaultConversionService();
- conversionService.addConverter(new StringArrayToStringConverter());
- conversionService.addConverter(new StringArrayToMapConverter());
- return conversionService;
}
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 35604650906..df46850b304 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
@@ -71,7 +71,6 @@
public class ServiceAnnotationBeanPostProcessor implements BeanDefinitionRegistryPostProcessor, EnvironmentAware,
ResourceLoaderAware, BeanClassLoaderAware {
- private static final String SEPARATOR = ":";
private final Logger logger = LoggerFactory.getLogger(getClass());
@@ -289,27 +288,10 @@ private void registerServiceBean(BeanDefinitionHolder beanDefinitionHolder, Bean
*/
private String generateServiceBeanName(Service service, Class> interfaceClass, String annotatedServiceBeanName) {
- StringBuilder beanNameBuilder = new StringBuilder(ServiceBean.class.getSimpleName());
+ ServiceBeanNameBuilder builder = ServiceBeanNameBuilder.create(service, interfaceClass, environment);
- beanNameBuilder.append(SEPARATOR).append(annotatedServiceBeanName);
- String interfaceClassName = interfaceClass.getName();
-
- beanNameBuilder.append(SEPARATOR).append(interfaceClassName);
-
- String version = service.version();
-
- if (StringUtils.hasText(version)) {
- beanNameBuilder.append(SEPARATOR).append(version);
- }
-
- String group = service.group();
-
- if (StringUtils.hasText(group)) {
- beanNameBuilder.append(SEPARATOR).append(group);
- }
-
- return beanNameBuilder.toString();
+ return builder.build();
}
diff --git a/dubbo-config/dubbo-config-spring/src/main/java/com/alibaba/dubbo/config/spring/beans/factory/annotation/ServiceBeanNameBuilder.java b/dubbo-config/dubbo-config-spring/src/main/java/com/alibaba/dubbo/config/spring/beans/factory/annotation/ServiceBeanNameBuilder.java
new file mode 100644
index 00000000000..b80840cf667
--- /dev/null
+++ b/dubbo-config/dubbo-config-spring/src/main/java/com/alibaba/dubbo/config/spring/beans/factory/annotation/ServiceBeanNameBuilder.java
@@ -0,0 +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.beans.factory.annotation;
+
+import com.alibaba.dubbo.config.annotation.Reference;
+import com.alibaba.dubbo.config.annotation.Service;
+import com.alibaba.dubbo.config.spring.ReferenceBean;
+import com.alibaba.dubbo.config.spring.ServiceBean;
+import org.springframework.core.env.Environment;
+import org.springframework.util.StringUtils;
+
+import static com.alibaba.dubbo.config.spring.util.AnnotationUtils.resolveInterfaceName;
+
+/**
+ * Dubbo {@link Service @Service} Bean Builder
+ *
+ * @see Service
+ * @see Reference
+ * @see ServiceBean
+ * @see ReferenceBean
+ * @since 2.6.5
+ */
+class ServiceBeanNameBuilder {
+
+ private static final String SEPARATOR = ":";
+
+ private final String interfaceClassName;
+
+ private final Environment environment;
+
+ // Optional
+ private String version;
+
+ private String group;
+
+ private ServiceBeanNameBuilder(String interfaceClassName, Environment environment) {
+ this.interfaceClassName = interfaceClassName;
+ this.environment = environment;
+ }
+
+ private ServiceBeanNameBuilder(Class> interfaceClass, Environment environment) {
+ this(interfaceClass.getName(), environment);
+ }
+
+ private ServiceBeanNameBuilder(Service service, Class> interfaceClass, Environment environment) {
+ this(resolveInterfaceName(service, interfaceClass), environment);
+ this.group(service.group());
+ this.version(service.version());
+ }
+
+ private ServiceBeanNameBuilder(Reference reference, Class> interfaceClass, Environment environment) {
+ this(resolveInterfaceName(reference, interfaceClass), environment);
+ this.group(reference.group());
+ this.version(reference.version());
+ }
+
+ public static ServiceBeanNameBuilder create(Class> interfaceClass, Environment environment) {
+ return new ServiceBeanNameBuilder(interfaceClass, environment);
+ }
+
+ public static ServiceBeanNameBuilder create(Service service, Class> interfaceClass, Environment environment) {
+ return new ServiceBeanNameBuilder(service, interfaceClass, environment);
+ }
+
+ public static ServiceBeanNameBuilder create(Reference reference, Class> interfaceClass, Environment environment) {
+ return new ServiceBeanNameBuilder(reference, interfaceClass, environment);
+ }
+
+ private static void append(StringBuilder builder, String value) {
+ if (StringUtils.hasText(value)) {
+ builder.append(value).append(SEPARATOR);
+ }
+ }
+
+ public ServiceBeanNameBuilder group(String group) {
+ this.group = group;
+ return this;
+ }
+
+ public ServiceBeanNameBuilder version(String version) {
+ this.version = version;
+ return this;
+ }
+
+ public String build() {
+ StringBuilder beanNameBuilder = new StringBuilder("ServiceBean").append(SEPARATOR);
+ // Required
+ append(beanNameBuilder, interfaceClassName);
+ // Optional
+ append(beanNameBuilder, version);
+ append(beanNameBuilder, group);
+ // Build and remove last ":"
+ String rawBeanName = beanNameBuilder.substring(0, beanNameBuilder.length() - 1);
+ // Resolve placeholders
+ return environment.resolvePlaceholders(rawBeanName);
+ }
+}
\ No newline at end of file
diff --git a/dubbo-config/dubbo-config-spring/src/main/java/com/alibaba/dubbo/config/spring/context/event/ServiceBeanExportedEvent.java b/dubbo-config/dubbo-config-spring/src/main/java/com/alibaba/dubbo/config/spring/context/event/ServiceBeanExportedEvent.java
new file mode 100644
index 00000000000..3b14d012040
--- /dev/null
+++ b/dubbo-config/dubbo-config-spring/src/main/java/com/alibaba/dubbo/config/spring/context/event/ServiceBeanExportedEvent.java
@@ -0,0 +1,50 @@
+/*
+ * 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.event;
+
+import com.alibaba.dubbo.config.spring.ServiceBean;
+import org.springframework.context.ApplicationEvent;
+import org.springframework.context.ApplicationListener;
+
+/**
+ * A {@link ApplicationEvent} after {@link ServiceBean} {@link ServiceBean#export() export} invocation
+ *
+ * @see ApplicationEvent
+ * @see ApplicationListener
+ * @see ServiceBean
+ * @since 2.6.5
+ */
+public class ServiceBeanExportedEvent extends ApplicationEvent {
+
+ /**
+ * Create a new ApplicationEvent.
+ *
+ * @param serviceBean {@link ServiceBean} bean
+ */
+ public ServiceBeanExportedEvent(ServiceBean serviceBean) {
+ super(serviceBean);
+ }
+
+ /**
+ * Get {@link ServiceBean} instance
+ *
+ * @return non-null
+ */
+ public ServiceBean getServiceBean() {
+ return (ServiceBean) super.getSource();
+ }
+}
diff --git a/dubbo-config/dubbo-config-spring/src/main/java/com/alibaba/dubbo/config/spring/convert/converter/StringArrayToMapConverter.java b/dubbo-config/dubbo-config-spring/src/main/java/com/alibaba/dubbo/config/spring/convert/converter/StringArrayToMapConverter.java
deleted file mode 100644
index 56c6d4c4ccd..00000000000
--- a/dubbo-config/dubbo-config-spring/src/main/java/com/alibaba/dubbo/config/spring/convert/converter/StringArrayToMapConverter.java
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package 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> {
-
- @Override
- public Map convert(String[] source) {
- return ObjectUtils.isEmpty(source) ? null : CollectionUtils.toStringMap(source);
- }
-
-}
diff --git a/dubbo-config/dubbo-config-spring/src/main/java/com/alibaba/dubbo/config/spring/convert/converter/StringArrayToStringConverter.java b/dubbo-config/dubbo-config-spring/src/main/java/com/alibaba/dubbo/config/spring/convert/converter/StringArrayToStringConverter.java
deleted file mode 100644
index 23e948b0644..00000000000
--- a/dubbo-config/dubbo-config-spring/src/main/java/com/alibaba/dubbo/config/spring/convert/converter/StringArrayToStringConverter.java
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package 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 {
-
- @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
index aa15e567eb0..f9b3c61ebd8 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
@@ -16,7 +16,11 @@
*/
package com.alibaba.dubbo.config.spring.util;
+import com.alibaba.dubbo.config.annotation.Reference;
+import com.alibaba.dubbo.config.annotation.Service;
+
import org.springframework.core.env.PropertyResolver;
+import org.springframework.util.StringUtils;
import java.lang.annotation.Annotation;
import java.util.HashSet;
@@ -86,4 +90,44 @@ public static Map getAttributes(Annotation annotation, PropertyR
}
-}
+ public static String resolveInterfaceName(Service service, Class> defaultInterfaceClass)
+ throws IllegalStateException {
+
+ String interfaceName;
+ if (StringUtils.hasText(service.interfaceName())) {
+ interfaceName = service.interfaceName();
+ } else if (!void.class.equals(service.interfaceClass())) {
+ interfaceName = service.interfaceClass().getName();
+ } else if (defaultInterfaceClass.isInterface()) {
+ interfaceName = defaultInterfaceClass.getName();
+ } else {
+ throw new IllegalStateException(
+ "The @Service undefined interfaceClass or interfaceName, and the type "
+ + defaultInterfaceClass.getName() + " is not a interface.");
+ }
+
+ return interfaceName;
+
+ }
+
+ public static String resolveInterfaceName(Reference reference, Class> defaultInterfaceClass)
+ throws IllegalStateException {
+
+ String interfaceName;
+ if (!"".equals(reference.interfaceName())) {
+ interfaceName = reference.interfaceName();
+ } else if (!void.class.equals(reference.interfaceClass())) {
+ interfaceName = reference.interfaceClass().getName();
+ } else if (defaultInterfaceClass.isInterface()) {
+ interfaceName = defaultInterfaceClass.getName();
+ } else {
+ throw new IllegalStateException(
+ "The @Reference undefined interfaceClass or interfaceName, and the type "
+ + defaultInterfaceClass.getName() + " is not a interface.");
+ }
+
+ return interfaceName;
+
+ }
+
+}
\ 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/ReferenceAnnotationBeanPostProcessorTest.java b/dubbo-config/dubbo-config-spring/src/test/java/com/alibaba/dubbo/config/spring/beans/factory/annotation/ReferenceAnnotationBeanPostProcessorTest.java
index a1b5807cbf9..eba43b2a599 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
@@ -19,26 +19,23 @@
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.After;
import org.junit.Assert;
-import org.junit.Before;
-import org.junit.BeforeClass;
import org.junit.Test;
+import org.junit.runner.RunWith;
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.annotation.Bean;
+import org.springframework.test.context.ContextConfiguration;
+import org.springframework.test.context.TestPropertySource;
+import org.springframework.test.context.junit4.SpringRunner;
import java.util.Collection;
import java.util.Map;
import static com.alibaba.dubbo.config.spring.beans.factory.annotation.ReferenceAnnotationBeanPostProcessor.BEAN_NAME;
-import static org.hamcrest.CoreMatchers.is;
-import static org.hamcrest.CoreMatchers.not;
-import static org.hamcrest.CoreMatchers.nullValue;
+import static org.hamcrest.CoreMatchers.*;
import static org.hamcrest.MatcherAssert.assertThat;
/**
@@ -46,50 +43,48 @@
*
* @since 2.5.7
*/
+@RunWith(SpringRunner.class)
+@ContextConfiguration(
+ classes = {
+ ServiceAnnotationTestConfiguration.class,
+ ReferenceAnnotationBeanPostProcessorTest.class
+ })
+@TestPropertySource(properties = {
+ "packagesToScan = com.alibaba.dubbo.config.spring.context.annotation.provider",
+ "consumer.version = ${demo.service.version}",
+ "consumer.url = dubbo://127.0.0.1:12345",
+})
public class ReferenceAnnotationBeanPostProcessorTest {
- 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");
+ @Bean
+ public TestBean testBean() {
+ return new TestBean();
}
- @Before
- public void init() {
- // Starts Provider
- providerApplicationContext = new AnnotationConfigApplicationContext(ServiceAnnotationBeanPostProcessorTest.TestConfiguration.class);
+ @Bean(BEAN_NAME)
+ public ReferenceAnnotationBeanPostProcessor referenceAnnotationBeanPostProcessor() {
+ return new ReferenceAnnotationBeanPostProcessor();
}
- @After
- public void destroy() {
- // Shutdowns Provider
- providerApplicationContext.close();
- }
+ @Autowired
+ private ConfigurableApplicationContext context;
@Test
public void test() throws Exception {
- AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(TestBean.class);
-
TestBean testBean = context.getBean(TestBean.class);
+ DemoService demoService = testBean.getDemoService();
+
+ Assert.assertEquals("Hello,Mercy", demoService.sayName("Mercy"));
+
Assert.assertNotNull(testBean.getDemoServiceFromAncestor());
Assert.assertNotNull(testBean.getDemoServiceFromParent());
Assert.assertNotNull(testBean.getDemoService());
- Assert.assertEquals(testBean.getDemoServiceFromAncestor(), testBean.getDemoServiceFromParent());
- Assert.assertEquals(testBean.getDemoService(), testBean.getDemoServiceFromParent());
-
- DemoService demoService = testBean.getDemoService();
-
- Assert.assertEquals("annotation:Mercy", demoService.sayName("Mercy"));
-
- context.close();
+ Assert.assertEquals("Hello,Mercy", testBean.getDemoServiceFromAncestor().sayName("Mercy"));
+ Assert.assertEquals("Hello,Mercy", testBean.getDemoServiceFromParent().sayName("Mercy"));
+ Assert.assertEquals("Hello,Mercy", testBean.getDemoService().sayName("Mercy"));
}
@@ -99,8 +94,6 @@ public void test() throws Exception {
@Test
public void testGetReferenceBeans() {
- AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(TestBean.class);
-
ReferenceAnnotationBeanPostProcessor beanPostProcessor = context.getBean(BEAN_NAME,
ReferenceAnnotationBeanPostProcessor.class);
@@ -112,17 +105,13 @@ public void testGetReferenceBeans() {
TestBean testBean = context.getBean(TestBean.class);
- Assert.assertEquals(referenceBean.get(), testBean.getDemoServiceFromAncestor());
- Assert.assertEquals(referenceBean.get(), testBean.getDemoServiceFromParent());
- Assert.assertEquals(referenceBean.get(), testBean.getDemoService());
+ Assert.assertNotNull(referenceBean.get());
}
@Test
public void testGetInjectedFieldReferenceBeanMap() {
- AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(TestBean.class);
-
ReferenceAnnotationBeanPostProcessor beanPostProcessor = context.getBean(BEAN_NAME,
ReferenceAnnotationBeanPostProcessor.class);
@@ -136,12 +125,12 @@ public void testGetInjectedFieldReferenceBeanMap() {
InjectionMetadata.InjectedElement injectedElement = entry.getKey();
- Assert.assertEquals("com.alibaba.dubbo.config.spring.beans.factory.annotation.ReferenceAnnotationBeanPostProcessor$ReferenceFieldElement",
+ Assert.assertEquals("com.alibaba.spring.beans.factory.annotation.AnnotationInjectedBeanPostProcessor$AnnotatedFieldElement",
injectedElement.getClass().getName());
ReferenceBean> referenceBean = entry.getValue();
- Assert.assertEquals("1.2", referenceBean.getVersion());
+ Assert.assertEquals("2.5.7", referenceBean.getVersion());
Assert.assertEquals("dubbo://127.0.0.1:12345", referenceBean.getUrl());
}
@@ -151,8 +140,6 @@ public void testGetInjectedFieldReferenceBeanMap() {
@Test
public void testGetInjectedMethodReferenceBeanMap() {
- AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(TestBean.class);
-
ReferenceAnnotationBeanPostProcessor beanPostProcessor = context.getBean(BEAN_NAME,
ReferenceAnnotationBeanPostProcessor.class);
@@ -166,36 +153,35 @@ public void testGetInjectedMethodReferenceBeanMap() {
InjectionMetadata.InjectedElement injectedElement = entry.getKey();
- Assert.assertEquals("com.alibaba.dubbo.config.spring.beans.factory.annotation.ReferenceAnnotationBeanPostProcessor$ReferenceMethodElement",
+ Assert.assertEquals("com.alibaba.spring.beans.factory.annotation.AnnotationInjectedBeanPostProcessor$AnnotatedMethodElement",
injectedElement.getClass().getName());
ReferenceBean> referenceBean = entry.getValue();
- Assert.assertEquals("1.2", referenceBean.getVersion());
+ Assert.assertEquals("2.5.7", referenceBean.getVersion());
Assert.assertEquals("dubbo://127.0.0.1:12345", referenceBean.getUrl());
}
}
- @Test
- public void testModuleInfo() {
- AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(TestBean.class);
-
- ReferenceAnnotationBeanPostProcessor beanPostProcessor = context.getBean(BEAN_NAME,
- ReferenceAnnotationBeanPostProcessor.class);
-
-
- Map> referenceBeanMap =
- beanPostProcessor.getInjectedMethodReferenceBeanMap();
-
- for (Map.Entry> entry : referenceBeanMap.entrySet()) {
- ReferenceBean> referenceBean = entry.getValue();
-
- assertThat(referenceBean.getModule().getName(),is("defaultModule"));
- assertThat(referenceBean.getMonitor(), not(nullValue()));
- }
- }
+// @Test
+// public void testModuleInfo() {
+//
+// ReferenceAnnotationBeanPostProcessor beanPostProcessor = context.getBean(BEAN_NAME,
+// ReferenceAnnotationBeanPostProcessor.class);
+//
+//
+// Map> referenceBeanMap =
+// beanPostProcessor.getInjectedMethodReferenceBeanMap();
+//
+// for (Map.Entry> entry : referenceBeanMap.entrySet()) {
+// ReferenceBean> referenceBean = entry.getValue();
+//
+// assertThat(referenceBean.getModule().getName(), is("defaultModule"));
+// assertThat(referenceBean.getMonitor(), not(nullValue()));
+// }
+// }
private static class AncestorBean {
@@ -209,7 +195,7 @@ public DemoService getDemoServiceFromAncestor() {
return demoServiceFromAncestor;
}
- @Reference(version = "1.2", url = "dubbo://127.0.0.1:12345")
+ @Reference(version = "2.5.7", url = "dubbo://127.0.0.1:12345")
public void setDemoServiceFromAncestor(DemoService demoServiceFromAncestor) {
this.demoServiceFromAncestor = demoServiceFromAncestor;
}
@@ -233,8 +219,6 @@ public DemoService getDemoServiceFromParent() {
}
- @ImportResource("META-INF/spring/dubbo-annotation-consumer.xml")
- @DubboComponentScan(basePackageClasses = ReferenceAnnotationBeanPostProcessorTest.class)
static class TestBean extends ParentBean {
private DemoService demoService;
@@ -246,7 +230,7 @@ public DemoService getDemoService() {
return demoService;
}
- @Reference(version = "1.2", url = "dubbo://127.0.0.1:12345")
+ @Reference(version = "2.5.7", url = "dubbo://127.0.0.1:12345")
public void setDemoService(DemoService demoService) {
this.demoService = demoService;
}
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 c0964418144..6133c48aaba 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
@@ -25,9 +25,6 @@
import org.springframework.beans.factory.annotation.Value;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.ComponentScan;
-import org.springframework.context.annotation.ImportResource;
-import org.springframework.context.annotation.PropertySource;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.TestPropertySource;
import org.springframework.test.context.junit4.SpringRunner;
@@ -41,17 +38,25 @@
*/
@RunWith(SpringRunner.class)
@ContextConfiguration(
- classes = {ServiceAnnotationBeanPostProcessorTest.TestConfiguration.class})
+ classes = {
+ ServiceAnnotationTestConfiguration.class,
+ ServiceAnnotationBeanPostProcessorTest.class
+ })
@TestPropertySource(properties = {
- "package1 = com.alibaba.dubbo.config.spring.context.annotation",
- "packagesToScan = ${package1}",
- "provider.version = 1.2"
+ "provider.package = com.alibaba.dubbo.config.spring.context.annotation.provider",
+ "packagesToScan = ${provider.package}",
})
public class ServiceAnnotationBeanPostProcessorTest {
@Autowired
private ConfigurableListableBeanFactory beanFactory;
+ @Bean
+ public ServiceAnnotationBeanPostProcessor serviceAnnotationBeanPostProcessor2
+ (@Value("${packagesToScan}") String... packagesToScan) {
+ return new ServiceAnnotationBeanPostProcessor(packagesToScan);
+ }
+
@Test
public void test() {
@@ -61,38 +66,16 @@ public void test() {
Map serviceBeansMap = beanFactory.getBeansOfType(ServiceBean.class);
- Assert.assertEquals(3, serviceBeansMap.size());
+ Assert.assertEquals(2, serviceBeansMap.size());
Map beanPostProcessorsMap =
beanFactory.getBeansOfType(ServiceAnnotationBeanPostProcessor.class);
- Assert.assertEquals(4, beanPostProcessorsMap.size());
+ Assert.assertEquals(2, beanPostProcessorsMap.size());
- Assert.assertTrue(beanPostProcessorsMap.containsKey("doubleServiceAnnotationBeanPostProcessor"));
- Assert.assertTrue(beanPostProcessorsMap.containsKey("emptyServiceAnnotationBeanPostProcessor"));
Assert.assertTrue(beanPostProcessorsMap.containsKey("serviceAnnotationBeanPostProcessor"));
Assert.assertTrue(beanPostProcessorsMap.containsKey("serviceAnnotationBeanPostProcessor2"));
}
- @ImportResource("META-INF/spring/dubbo-annotation-provider.xml")
- @PropertySource("META-INF/default.properties")
- @ComponentScan("com.alibaba.dubbo.config.spring.context.annotation.provider")
- public static class TestConfiguration {
-
- @Bean
- public ServiceAnnotationBeanPostProcessor serviceAnnotationBeanPostProcessor
- (@Value("${packagesToScan}") String... packagesToScan) {
- return new ServiceAnnotationBeanPostProcessor(packagesToScan);
- }
-
- @Bean
- public ServiceAnnotationBeanPostProcessor serviceAnnotationBeanPostProcessor2
- (@Value("${packagesToScan}") String... packagesToScan) {
- return new ServiceAnnotationBeanPostProcessor(packagesToScan);
- }
-
-
- }
-
}
diff --git a/dubbo-config/dubbo-config-spring/src/test/java/com/alibaba/dubbo/config/spring/beans/factory/annotation/ServiceAnnotationTestConfiguration.java b/dubbo-config/dubbo-config-spring/src/test/java/com/alibaba/dubbo/config/spring/beans/factory/annotation/ServiceAnnotationTestConfiguration.java
new file mode 100644
index 00000000000..2e20797fa15
--- /dev/null
+++ b/dubbo-config/dubbo-config-spring/src/test/java/com/alibaba/dubbo/config/spring/beans/factory/annotation/ServiceAnnotationTestConfiguration.java
@@ -0,0 +1,114 @@
+/*
+ * 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.ProtocolConfig;
+import com.alibaba.dubbo.config.RegistryConfig;
+import com.alibaba.dubbo.config.annotation.Service;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Primary;
+import org.springframework.context.annotation.PropertySource;
+import org.springframework.transaction.PlatformTransactionManager;
+import org.springframework.transaction.TransactionDefinition;
+import org.springframework.transaction.TransactionException;
+import org.springframework.transaction.TransactionStatus;
+
+/**
+ * {@link Service} Bean
+ *
+ * @since 2.6.5
+ */
+@PropertySource("META-INF/default.properties")
+public class ServiceAnnotationTestConfiguration {
+
+ /**
+ * Current application configuration, to replace XML config:
+ *
+ * <dubbo:application name="dubbo-annotation-provider"/>
+ *
+ *
+ * @return {@link ApplicationConfig} Bean
+ */
+ @Bean("dubbo-annotation-provider")
+ public ApplicationConfig applicationConfig() {
+ ApplicationConfig applicationConfig = new ApplicationConfig();
+ applicationConfig.setName("dubbo-annotation-provider");
+ return applicationConfig;
+ }
+
+ /**
+ * Current registry center configuration, to replace XML config:
+ *
+ * <dubbo:registry id="my-registry" address="N/A"/>
+ *
+ *
+ * @return {@link RegistryConfig} Bean
+ */
+ @Bean("my-registry")
+ public RegistryConfig registryConfig() {
+ RegistryConfig registryConfig = new RegistryConfig();
+ registryConfig.setAddress("N/A");
+ return registryConfig;
+ }
+
+ /**
+ * Current protocol configuration, to replace XML config:
+ *
+ * <dubbo:protocol name="dubbo" port="12345"/>
+ *
+ *
+ * @return {@link ProtocolConfig} Bean
+ */
+ @Bean("dubbo")
+ public ProtocolConfig protocolConfig() {
+ ProtocolConfig protocolConfig = new ProtocolConfig();
+ protocolConfig.setName("dubbo");
+ protocolConfig.setPort(12345);
+ return protocolConfig;
+ }
+
+ @Primary
+ @Bean
+ public PlatformTransactionManager platformTransactionManager() {
+ return new PlatformTransactionManager() {
+
+ @Override
+ public TransactionStatus getTransaction(TransactionDefinition definition) throws TransactionException {
+ return null;
+ }
+
+ @Override
+ public void commit(TransactionStatus status) throws TransactionException {
+
+ }
+
+ @Override
+ public void rollback(TransactionStatus status) throws TransactionException {
+
+ }
+ };
+ }
+
+ @Bean
+ public ServiceAnnotationBeanPostProcessor serviceAnnotationBeanPostProcessor
+ (@Value("${packagesToScan}") String... packagesToScan) {
+ return new ServiceAnnotationBeanPostProcessor(packagesToScan);
+ }
+
+}
\ 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/ServiceBeanNameBuilderTest.java b/dubbo-config/dubbo-config-spring/src/test/java/com/alibaba/dubbo/config/spring/beans/factory/annotation/ServiceBeanNameBuilderTest.java
new file mode 100644
index 00000000000..8ee0c4b2d48
--- /dev/null
+++ b/dubbo-config/dubbo-config-spring/src/test/java/com/alibaba/dubbo/config/spring/beans/factory/annotation/ServiceBeanNameBuilderTest.java
@@ -0,0 +1,75 @@
+/*
+ * 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.annotation.Reference;
+import com.alibaba.dubbo.config.annotation.Service;
+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.mock.env.MockEnvironment;
+import org.springframework.util.ReflectionUtils;
+
+import static com.alibaba.dubbo.config.spring.beans.factory.annotation.ServiceBeanNameBuilderTest.GROUP;
+import static com.alibaba.dubbo.config.spring.beans.factory.annotation.ServiceBeanNameBuilderTest.VERSION;
+
+/**
+ * {@link ServiceBeanNameBuilder} Test
+ *
+ * @see ServiceBeanNameBuilder
+ * @since 2.6.5
+ */
+@Service(interfaceClass = DemoService.class, group = GROUP, version = VERSION,
+ application = "application", module = "module", registry = {"1", "2", "3"})
+public class ServiceBeanNameBuilderTest {
+
+ @Reference(interfaceClass = DemoService.class, group = "DUBBO", version = "1.0.0",
+ application = "application", module = "module", registry = {"1", "2", "3"})
+ static final Class> INTERFACE_CLASS = DemoService.class;
+
+ static final String GROUP = "DUBBO";
+
+ static final String VERSION = "1.0.0";
+
+ static final String BEAN_NAME = "ServiceBean:com.alibaba.dubbo.config.spring.api.DemoService:1.0.0:DUBBO";
+
+ private MockEnvironment environment = new MockEnvironment();
+
+ @Test
+ public void testRequiredAttributes() {
+ ServiceBeanNameBuilder builder = ServiceBeanNameBuilder.create(INTERFACE_CLASS, environment);
+ Assert.assertEquals("ServiceBean:com.alibaba.dubbo.config.spring.api.DemoService", builder.build());
+ }
+
+ @Test
+ public void testServiceAnnotation() {
+ Service service = AnnotationUtils.getAnnotation(ServiceBeanNameBuilderTest.class, Service.class);
+ ServiceBeanNameBuilder builder = ServiceBeanNameBuilder.create(service, INTERFACE_CLASS, environment);
+ Assert.assertEquals(BEAN_NAME,
+ builder.build());
+ }
+
+ @Test
+ public void testReferenceAnnotation() {
+ Reference reference = AnnotationUtils.getAnnotation(ReflectionUtils.findField(ServiceBeanNameBuilderTest.class, "INTERFACE_CLASS"), Reference.class);
+ ServiceBeanNameBuilder builder = ServiceBeanNameBuilder.create(reference, INTERFACE_CLASS, environment);
+ Assert.assertEquals(BEAN_NAME,
+ builder.build());
+ }
+
+}
diff --git a/dubbo-config/dubbo-config-spring/src/test/java/com/alibaba/dubbo/config/spring/convert/converter/StringArrayToMapConverterTest.java b/dubbo-config/dubbo-config-spring/src/test/java/com/alibaba/dubbo/config/spring/convert/converter/StringArrayToMapConverterTest.java
deleted file mode 100644
index 51be7c3f2f2..00000000000
--- a/dubbo-config/dubbo-config-spring/src/test/java/com/alibaba/dubbo/config/spring/convert/converter/StringArrayToMapConverterTest.java
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package 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 value = converter.convert(new String[]{"Hello", "World"});
-
- Map expected = new LinkedHashMap();
-
- 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/convert/converter/StringArrayToStringConverterTest.java b/dubbo-config/dubbo-config-spring/src/test/java/com/alibaba/dubbo/config/spring/convert/converter/StringArrayToStringConverterTest.java
deleted file mode 100644
index 67e82479235..00000000000
--- a/dubbo-config/dubbo-config-spring/src/test/java/com/alibaba/dubbo/config/spring/convert/converter/StringArrayToStringConverterTest.java
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package 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);
-
- }
-
-}