You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@dubbo.apache.org by al...@apache.org on 2021/08/10 03:25:47 UTC
[dubbo] branch 3.0 updated: [3.0] compatible with spring 3.2.x and
add tests (#8430)
This is an automated email from the ASF dual-hosted git repository.
albumenj pushed a commit to branch 3.0
in repository https://gitbox.apache.org/repos/asf/dubbo.git
The following commit(s) were added to refs/heads/3.0 by this push:
new 649dc5b [3.0] compatible with spring 3.2.x and add tests (#8430)
649dc5b is described below
commit 649dc5b396fe57e34cb13a1b6469d8ea496db387
Author: Gong Dewei <ky...@qq.com>
AuthorDate: Tue Aug 10 11:25:11 2021 +0800
[3.0] compatible with spring 3.2.x and add tests (#8430)
* compatible with spring 3.2.x and add tests
* add licence
* polish spring tests, fix compatible issue of spring 4.1
* polish code
* add skip_maven_deploy
* adjust spring test module
* polish log
* remove unused imports
* Fix NPE
---
.../apache/dubbo/common/utils/AnnotationUtils.java | 5 +
.../ReferenceAnnotationBeanPostProcessor.java | 42 +++-
.../annotation/ServiceAnnotationPostProcessor.java | 66 ++++--
.../context/DubboBootstrapApplicationListener.java | 10 +-
.../DubboInfraBeanRegisterPostProcessor.java | 17 +-
.../annotation/DubboComponentScanRegistrar.java | 38 +++-
.../spring/reference/ReferenceBeanSupport.java | 12 +-
.../spring/schema/DubboBeanDefinitionParser.java | 17 +-
.../dubbo/config/spring/util/DubboBeanUtils.java | 4 +-
.../config/spring/util/SpringCompatUtils.java | 124 +++++++++++
.../config/ServiceBeanIdConflictProcessor.java | 5 +-
dubbo-test/dubbo-test-common/pom.xml | 61 ++++++
.../dubbo/test/common/EmbeddedZooKeeper.java | 244 +++++++++++++++++++++
.../org/apache/dubbo/test/common/ErrorHandler.java | 27 +++
.../org/apache/dubbo/test/common/SysProps.java | 45 ++++
.../apache/dubbo/test/common/ZooKeeperServer.java | 43 ++++
.../apache/dubbo/test/common/api/DemoService.java | 27 +++
.../dubbo/test/common/api/GreetingService.java | 24 ++
.../dubbo/test/common/api/RestDemoService.java | 45 ++++
.../dubbo/test/common/impl/DemoServiceImpl.java | 43 ++++
.../test/common/impl/GreetingServiceImpl.java | 30 +++
.../test/common/impl/RestDemoServiceImpl.java | 58 +++++
dubbo-test/dubbo-test-spring/pom.xml | 170 ++++++++++++++
.../test/spring/SpringAnnotationBeanTest.java | 67 ++++++
.../test/spring/SpringJavaConfigBeanTest.java | 186 ++++++++++++++++
.../dubbo/test/spring/SpringXmlConfigTest.java | 66 ++++++
.../src/main/resources/demo-app.properties | 11 +
.../src/main/resources/log4j.properties | 7 +
.../src/main/resources/spring/dubbo-demo.xml | 53 +++++
dubbo-test/dubbo-test-spring3.2/pom.xml | 70 ++++++
dubbo-test/dubbo-test-spring4.1/pom.xml | 70 ++++++
dubbo-test/dubbo-test-spring4.2/pom.xml | 70 ++++++
dubbo-test/pom.xml | 56 +++++
pom.xml | 2 +
34 files changed, 1754 insertions(+), 61 deletions(-)
diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/utils/AnnotationUtils.java b/dubbo-common/src/main/java/org/apache/dubbo/common/utils/AnnotationUtils.java
index ba2da5b..770694e 100644
--- a/dubbo-common/src/main/java/org/apache/dubbo/common/utils/AnnotationUtils.java
+++ b/dubbo-common/src/main/java/org/apache/dubbo/common/utils/AnnotationUtils.java
@@ -495,6 +495,11 @@ public interface AnnotationUtils {
filteredAttributes.put(key, val);
}
});
+ // remove void class, compatible with spring 3.x
+ Object interfaceClassValue = filteredAttributes.get("interfaceClass");
+ if (interfaceClassValue instanceof String && StringUtils.isEquals((String) interfaceClassValue, "void")) {
+ filteredAttributes.remove("interfaceClass");
+ }
return filteredAttributes;
}
diff --git a/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/beans/factory/annotation/ReferenceAnnotationBeanPostProcessor.java b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/beans/factory/annotation/ReferenceAnnotationBeanPostProcessor.java
index 71591f7..fe5af61 100644
--- a/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/beans/factory/annotation/ReferenceAnnotationBeanPostProcessor.java
+++ b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/beans/factory/annotation/ReferenceAnnotationBeanPostProcessor.java
@@ -30,6 +30,7 @@ import org.apache.dubbo.config.spring.reference.ReferenceAttributes;
import org.apache.dubbo.config.spring.ReferenceBean;
import org.apache.dubbo.config.spring.reference.ReferenceBeanManager;
import org.apache.dubbo.config.spring.reference.ReferenceBeanSupport;
+import org.apache.dubbo.config.spring.util.SpringCompatUtils;
import org.apache.dubbo.rpc.service.GenericService;
import org.springframework.beans.BeansException;
import org.springframework.beans.PropertyValue;
@@ -40,7 +41,9 @@ import org.springframework.beans.factory.annotation.InjectionMetadata;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.BeanDefinitionHolder;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
+import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
+import org.springframework.beans.factory.support.AbstractBeanFactory;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.GenericBeanDefinition;
import org.springframework.beans.factory.support.RootBeanDefinition;
@@ -63,6 +66,7 @@ import java.util.concurrent.ConcurrentMap;
import static com.alibaba.spring.util.AnnotationUtils.getAttribute;
import static org.apache.dubbo.common.utils.AnnotationUtils.filterDefaultValues;
+import static org.apache.dubbo.config.spring.util.SpringCompatUtils.getPropertyValue;
import static org.springframework.util.StringUtils.hasText;
/**
@@ -156,16 +160,24 @@ public class ReferenceAnnotationBeanPostProcessor extends AbstractAnnotationBean
}
}
- // This bean has bean register as BeanPostProcessor at org.apache.dubbo.config.spring.context.DubboInfraBeanRegisterPostProcessor.postProcessBeanFactory()
- // so destroy this bean here, prevent register it as BeanPostProcessor again, avoid cause BeanPostProcessorChecker detection error
- beanDefinitionRegistry.removeBeanDefinition(BEAN_NAME);
+ if (beanFactory instanceof AbstractBeanFactory) {
+ List<BeanPostProcessor> beanPostProcessors = ((AbstractBeanFactory) beanFactory).getBeanPostProcessors();
+ for (BeanPostProcessor beanPostProcessor : beanPostProcessors) {
+ if (beanPostProcessor == this) {
+ // This bean has bean register as BeanPostProcessor at org.apache.dubbo.config.spring.context.DubboInfraBeanRegisterPostProcessor.postProcessBeanFactory()
+ // so destroy this bean here, prevent register it as BeanPostProcessor again, avoid cause BeanPostProcessorChecker detection error
+ beanDefinitionRegistry.removeBeanDefinition(BEAN_NAME);
+ break;
+ }
+ }
+ }
try {
// this is an early event, it will be notified at org.springframework.context.support.AbstractApplicationContext.registerListeners()
applicationContext.publishEvent(new DubboAnnotationInitedEvent(applicationContext));
} catch (Exception e) {
// if spring version is less then 4.2, it does not support early application event
- logger.error("publish early application event failed, please upgrade spring version to 4.2.x or later", e);
+ logger.warn("publish early application event failed, please upgrade spring version to 4.2.x or later: " + e);
}
}
@@ -175,11 +187,8 @@ public class ReferenceAnnotationBeanPostProcessor extends AbstractAnnotationBean
private boolean isAnnotatedReferenceBean(BeanDefinition beanDefinition) {
if (beanDefinition instanceof AnnotatedBeanDefinition) {
AnnotatedBeanDefinition annotatedBeanDefinition = (AnnotatedBeanDefinition) beanDefinition;
- if (annotatedBeanDefinition.getFactoryMethodMetadata() == null) {
- return false;
- }
- String beanClassName = annotatedBeanDefinition.getFactoryMethodMetadata().getReturnTypeName();
- if (ReferenceBean.class.getName().equals(beanClassName)) {
+ String beanClassName = SpringCompatUtils.getFactoryMethodReturnType(annotatedBeanDefinition);
+ if (beanClassName != null && ReferenceBean.class.getName().equals(beanClassName)) {
return true;
}
}
@@ -205,10 +214,19 @@ public class ReferenceAnnotationBeanPostProcessor extends AbstractAnnotationBean
*/
private void processReferenceAnnotatedBeanDefinition(String beanName, AnnotatedBeanDefinition beanDefinition) {
+ MethodMetadata factoryMethodMetadata = SpringCompatUtils.getFactoryMethodMetadata(beanDefinition);
+
// Extract beanClass from generic return type of java-config bean method: ReferenceBean<DemoService>
// see org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.getTypeForFactoryBeanFromMethod
Class beanClass = getBeanFactory().getType(beanName);
- MethodMetadata factoryMethodMetadata = beanDefinition.getFactoryMethodMetadata();
+ if (beanClass == Object.class) {
+ beanClass = SpringCompatUtils.getGenericTypeOfReturnType(factoryMethodMetadata);
+ }
+ if (beanClass == Object.class) {
+ // bean class is invalid, ignore it
+ return;
+ }
+
if (beanClass == null) {
String beanMethodSignature = factoryMethodMetadata.getDeclaringClassName()+"#"+factoryMethodMetadata.getMethodName()+"()";
throw new BeanCreationException("The ReferenceBean is missing necessary generic type, which returned by the @Bean method of Java-config class. " +
@@ -239,6 +257,7 @@ public class ReferenceAnnotationBeanPostProcessor extends AbstractAnnotationBean
// get interface
String interfaceName = (String) attributes.get(ReferenceAttributes.INTERFACE);
+
// check beanClass and reference interface class
if (!StringUtils.isEquals(interfaceName, beanClass.getName()) && beanClass != GenericService.class) {
String beanMethodSignature = factoryMethodMetadata.getDeclaringClassName()+"#"+factoryMethodMetadata.getMethodName()+"()";
@@ -466,7 +485,8 @@ public class ReferenceAnnotationBeanPostProcessor extends AbstractAnnotationBean
// see org.springframework.beans.factory.support.AbstractBeanFactory#getTypeForFactoryBean()
GenericBeanDefinition targetDefinition = new GenericBeanDefinition();
targetDefinition.setBeanClass(interfaceClass);
- String id = (String) beanDefinition.getPropertyValues().get(ReferenceAttributes.ID);
+ String id = getPropertyValue(beanDefinition.getPropertyValues(), ReferenceAttributes.ID);
+
beanDefinition.setDecoratedDefinition(new BeanDefinitionHolder(targetDefinition, id+"_decorated"));
// signal object type since Spring 5.2
diff --git a/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/beans/factory/annotation/ServiceAnnotationPostProcessor.java b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/beans/factory/annotation/ServiceAnnotationPostProcessor.java
index a23e8be..9313315 100644
--- a/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/beans/factory/annotation/ServiceAnnotationPostProcessor.java
+++ b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/beans/factory/annotation/ServiceAnnotationPostProcessor.java
@@ -29,10 +29,12 @@ import org.apache.dubbo.config.spring.ServiceBean;
import org.apache.dubbo.config.spring.context.annotation.DubboClassPathBeanDefinitionScanner;
import org.apache.dubbo.config.spring.schema.AnnotationBeanDefinitionParser;
import org.apache.dubbo.config.spring.util.DubboAnnotationUtils;
+import org.apache.dubbo.config.spring.util.SpringCompatUtils;
import org.springframework.beans.BeansException;
import org.springframework.beans.MutablePropertyValues;
import org.springframework.beans.factory.BeanClassLoaderAware;
import org.springframework.beans.factory.BeanDefinitionStoreException;
+import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.AnnotatedBeanDefinition;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.BeanDefinitionHolder;
@@ -77,11 +79,11 @@ import java.util.Set;
import static com.alibaba.spring.util.ObjectUtils.of;
import static java.util.Arrays.asList;
import static org.apache.dubbo.common.utils.AnnotationUtils.filterDefaultValues;
+import static org.apache.dubbo.common.utils.AnnotationUtils.findAnnotation;
import static org.apache.dubbo.config.spring.beans.factory.annotation.ServiceBeanNameBuilder.create;
import static org.apache.dubbo.config.spring.util.DubboAnnotationUtils.resolveInterfaceName;
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.AnnotatedElementUtils.findMergedAnnotation;
import static org.springframework.util.ClassUtils.resolveClassName;
/**
@@ -94,7 +96,7 @@ import static org.springframework.util.ClassUtils.resolveClassName;
* @since 2.7.7
*/
public class ServiceAnnotationPostProcessor implements BeanDefinitionRegistryPostProcessor, EnvironmentAware,
- ResourceLoaderAware, BeanClassLoaderAware, ApplicationContextAware {
+ ResourceLoaderAware, BeanClassLoaderAware, ApplicationContextAware, InitializingBean {
public static final String BEAN_NAME = "dubboServiceAnnotationPostProcessor";
@@ -111,6 +113,7 @@ public class ServiceAnnotationPostProcessor implements BeanDefinitionRegistryPos
protected final Set<String> packagesToScan;
+ private Set<String> resolvedPackagesToScan;
private Environment environment;
@@ -122,6 +125,7 @@ public class ServiceAnnotationPostProcessor implements BeanDefinitionRegistryPos
private ServicePackagesHolder servicePackagesHolder;
+ private volatile boolean scaned = false;
public ServiceAnnotationPostProcessor(String... packagesToScan) {
this(asList(packagesToScan));
@@ -136,19 +140,38 @@ public class ServiceAnnotationPostProcessor implements BeanDefinitionRegistryPos
}
@Override
+ public void afterPropertiesSet() throws Exception {
+ this.resolvedPackagesToScan = resolvePackagesToScan(packagesToScan);
+ }
+
+ @Override
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
this.registry = registry;
+ scanServiceBeans(resolvedPackagesToScan, registry);
+ }
- Set<String> resolvedPackagesToScan = resolvePackagesToScan(packagesToScan);
+ @Override
+ public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
+ if (this.registry == null) {
+ // In spring 3.x, may be not call postProcessBeanDefinitionRegistry()
+ this.registry = (BeanDefinitionRegistry) beanFactory;
+ }
- if (!CollectionUtils.isEmpty(resolvedPackagesToScan)) {
- scanServiceBeans(resolvedPackagesToScan, registry);
- } else {
- if (logger.isWarnEnabled()) {
- logger.warn("packagesToScan is empty , ServiceBean registry will be ignored!");
+ // scan bean definitions
+ String[] beanNames = beanFactory.getBeanDefinitionNames();
+ for (String beanName : beanNames) {
+ BeanDefinition beanDefinition = beanFactory.getBeanDefinition(beanName);
+ Map<String, Object> annotationAttributes = getServiceAnnotationAttributes(beanDefinition);
+ if (annotationAttributes != null) {
+ // process @DubboService at java-config @bean method
+ processAnnotatedBeanDefinition(beanName, (AnnotatedBeanDefinition) beanDefinition, annotationAttributes);
}
}
+ if (!scaned) {
+ // In spring 3.x, may be not call postProcessBeanDefinitionRegistry(), so scan service class here
+ scanServiceBeans(resolvedPackagesToScan, registry);
+ }
}
/**
@@ -159,6 +182,14 @@ public class ServiceAnnotationPostProcessor implements BeanDefinitionRegistryPos
*/
private void scanServiceBeans(Set<String> packagesToScan, BeanDefinitionRegistry registry) {
+ scaned = true;
+ if (CollectionUtils.isEmpty(packagesToScan)) {
+ if (logger.isWarnEnabled()) {
+ logger.warn("packagesToScan is empty , ServiceBean registry will be ignored!");
+ }
+ return;
+ }
+
DubboClassPathBeanDefinitionScanner scanner =
new DubboClassPathBeanDefinitionScanner(registry, environment, resourceLoader);
@@ -325,7 +356,7 @@ public class ServiceAnnotationPostProcessor implements BeanDefinitionRegistryPos
private Annotation findServiceAnnotation(Class<?> beanClass) {
return serviceAnnotationTypes
.stream()
- .map(annotationType -> findMergedAnnotation(beanClass, annotationType))
+ .map(annotationType -> findAnnotation(beanClass, annotationType))
.filter(Objects::nonNull)
.findFirst()
.orElse(null);
@@ -482,19 +513,6 @@ public class ServiceAnnotationPostProcessor implements BeanDefinitionRegistryPos
builder.addPropertyValue(propertyName, resolvedBeanName);
}
- @Override
- public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
- String[] beanNames = beanFactory.getBeanDefinitionNames();
- for (String beanName : beanNames) {
- BeanDefinition beanDefinition = beanFactory.getBeanDefinition(beanName);
- Map<String, Object> annotationAttributes = getServiceAnnotationAttributes(beanDefinition);
- if (annotationAttributes != null) {
- // process @DubboService at java-config @bean method
- processAnnotatedBeanDefinition(beanName, (AnnotatedBeanDefinition) beanDefinition, annotationAttributes);
- }
- }
- }
-
/**
* Get dubbo service annotation class at java-config @bean method
* @return return service annotation attributes map if found, or return null if not found.
@@ -502,7 +520,7 @@ public class ServiceAnnotationPostProcessor implements BeanDefinitionRegistryPos
private Map<String, Object> getServiceAnnotationAttributes(BeanDefinition beanDefinition) {
if (beanDefinition instanceof AnnotatedBeanDefinition) {
AnnotatedBeanDefinition annotatedBeanDefinition = (AnnotatedBeanDefinition) beanDefinition;
- MethodMetadata factoryMethodMetadata = annotatedBeanDefinition.getFactoryMethodMetadata();
+ MethodMetadata factoryMethodMetadata = SpringCompatUtils.getFactoryMethodMetadata(annotatedBeanDefinition);
if (factoryMethodMetadata != null) {
// try all dubbo service annotation types
for (Class<? extends Annotation> annotationType : serviceAnnotationTypes) {
@@ -542,7 +560,7 @@ public class ServiceAnnotationPostProcessor implements BeanDefinitionRegistryPos
Map<String, Object> serviceAnnotationAttributes = new LinkedHashMap<>(attributes);
// get bean class from return type
- String returnTypeName = refServiceBeanDefinition.getFactoryMethodMetadata().getReturnTypeName();
+ String returnTypeName = SpringCompatUtils.getFactoryMethodReturnType(refServiceBeanDefinition);
Class<?> beanClass = resolveClassName(returnTypeName, classLoader);
String serviceInterface = resolveInterfaceName(serviceAnnotationAttributes, beanClass);
diff --git a/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/context/DubboBootstrapApplicationListener.java b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/context/DubboBootstrapApplicationListener.java
index 90d0680..ffb1335 100644
--- a/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/context/DubboBootstrapApplicationListener.java
+++ b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/context/DubboBootstrapApplicationListener.java
@@ -54,11 +54,17 @@ public class DubboBootstrapApplicationListener implements ApplicationListener, A
private final DubboBootstrap dubboBootstrap;
private ApplicationContext applicationContext;
+ private boolean shouldInitConfigBeans;
public DubboBootstrapApplicationListener() {
this.dubboBootstrap = initBootstrap();
}
+ public DubboBootstrapApplicationListener(boolean shouldInitConfigBeans) {
+ this.dubboBootstrap = initBootstrap();
+ this.shouldInitConfigBeans = shouldInitConfigBeans;
+ }
+
private DubboBootstrap initBootstrap() {
DubboBootstrap dubboBootstrap = DubboBootstrap.getInstance();
if (dubboBootstrap.getTakeoverMode() != BootstrapTakeoverMode.MANUAL) {
@@ -142,7 +148,9 @@ public class DubboBootstrapApplicationListener implements ApplicationListener, A
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.applicationContext = applicationContext;
- checkCallStackAndInit();
+ if (shouldInitConfigBeans) {
+ checkCallStackAndInit();
+ }
}
private void checkCallStackAndInit() {
diff --git a/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/context/DubboInfraBeanRegisterPostProcessor.java b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/context/DubboInfraBeanRegisterPostProcessor.java
index 2c56100..7952982 100644
--- a/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/context/DubboInfraBeanRegisterPostProcessor.java
+++ b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/context/DubboInfraBeanRegisterPostProcessor.java
@@ -58,14 +58,17 @@ public class DubboInfraBeanRegisterPostProcessor implements BeanDefinitionRegist
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
- // register ReferenceAnnotationBeanPostProcessor early before PropertySourcesPlaceholderConfigurer/PropertyPlaceholderConfigurer
- // for processing early init ReferenceBean
- ReferenceAnnotationBeanPostProcessor referenceAnnotationBeanPostProcessor = beanFactory.getBean(
- ReferenceAnnotationBeanPostProcessor.BEAN_NAME, ReferenceAnnotationBeanPostProcessor.class);
- beanFactory.addBeanPostProcessor(referenceAnnotationBeanPostProcessor);
+ // In Spring 3.2.x, registry may be null because do not calling postProcessBeanDefinitionRegistry method before postProcessBeanFactory
+ if (registry != null) {
+ // register ReferenceAnnotationBeanPostProcessor early before PropertySourcesPlaceholderConfigurer/PropertyPlaceholderConfigurer
+ // for processing early init ReferenceBean
+ ReferenceAnnotationBeanPostProcessor referenceAnnotationBeanPostProcessor = beanFactory.getBean(
+ ReferenceAnnotationBeanPostProcessor.BEAN_NAME, ReferenceAnnotationBeanPostProcessor.class);
+ beanFactory.addBeanPostProcessor(referenceAnnotationBeanPostProcessor);
- // register PropertySourcesPlaceholderConfigurer bean if not exits
- DubboBeanUtils.registerBeansIfNotExists(beanFactory, registry);
+ // register PropertySourcesPlaceholderConfigurer bean if not exits
+ DubboBeanUtils.registerPlaceholderConfigurerBeanIfNotExists(beanFactory, registry);
+ }
// Initialize dubbo Environment before ConfigManager
// Extract dubbo props from Spring env and put them to app config
diff --git a/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/context/annotation/DubboComponentScanRegistrar.java b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/context/annotation/DubboComponentScanRegistrar.java
index 7807efe..25821d2 100644
--- a/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/context/annotation/DubboComponentScanRegistrar.java
+++ b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/context/annotation/DubboComponentScanRegistrar.java
@@ -79,19 +79,41 @@ public class DubboComponentScanRegistrar implements ImportBeanDefinitionRegistra
}
private Set<String> getPackagesToScan(AnnotationMetadata metadata) {
+ // get from @DubboComponentScan
+ Set<String> packagesToScan = getPackagesToScan0(metadata, DubboComponentScan.class, "basePackages", "basePackageClasses");
+
+ // get from @EnableDubbo, compatible with spring 3.x
+ if (packagesToScan.isEmpty()) {
+ packagesToScan = getPackagesToScan0(metadata, EnableDubbo.class, "scanBasePackages", "scanBasePackageClasses");
+ }
+
+ if (packagesToScan.isEmpty()) {
+ return Collections.singleton(ClassUtils.getPackageName(metadata.getClassName()));
+ }
+ return packagesToScan;
+ }
+
+ private Set<String> getPackagesToScan0(AnnotationMetadata metadata, Class annotationClass, String basePackagesName, String basePackageClassesName) {
+
AnnotationAttributes attributes = AnnotationAttributes.fromMap(
- metadata.getAnnotationAttributes(DubboComponentScan.class.getName()));
- String[] basePackages = attributes.getStringArray("basePackages");
- Class<?>[] basePackageClasses = attributes.getClassArray("basePackageClasses");
- String[] value = attributes.getStringArray("value");
- // Appends value array attributes
- Set<String> packagesToScan = new LinkedHashSet<String>(Arrays.asList(value));
+ metadata.getAnnotationAttributes(annotationClass.getName()));
+ if (attributes == null) {
+ return Collections.emptySet();
+ }
+
+ Set<String> packagesToScan = new LinkedHashSet<>();
+ // basePackages
+ String[] basePackages = attributes.getStringArray(basePackagesName);
packagesToScan.addAll(Arrays.asList(basePackages));
+ // basePackageClasses
+ Class<?>[] basePackageClasses = attributes.getClassArray(basePackageClassesName);
for (Class<?> basePackageClass : basePackageClasses) {
packagesToScan.add(ClassUtils.getPackageName(basePackageClass));
}
- if (packagesToScan.isEmpty()) {
- return Collections.singleton(ClassUtils.getPackageName(metadata.getClassName()));
+ // value
+ if (attributes.containsKey("value")) {
+ String[] value = attributes.getStringArray("value");
+ packagesToScan.addAll(Arrays.asList(value));
}
return packagesToScan;
}
diff --git a/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/reference/ReferenceBeanSupport.java b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/reference/ReferenceBeanSupport.java
index dfdb19a..066ea0b 100644
--- a/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/reference/ReferenceBeanSupport.java
+++ b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/reference/ReferenceBeanSupport.java
@@ -58,8 +58,16 @@ public class ReferenceBeanSupport {
interfaceName = (String) attributes.get(ReferenceAttributes.INTERFACE_NAME);
}
if (interfaceName == null) {
- Class clazz = (Class) attributes.get(ReferenceAttributes.INTERFACE_CLASS);
- interfaceName = clazz != null ? clazz.getName() : null;
+ Object interfaceClassValue = attributes.get(ReferenceAttributes.INTERFACE_CLASS);
+ if (interfaceClassValue instanceof Class) {
+ interfaceName = ((Class) interfaceClassValue).getName();
+ } else if (interfaceClassValue instanceof String) {
+ if (interfaceClassValue.equals("void")) {
+ attributes.remove(ReferenceAttributes.INTERFACE_CLASS);
+ } else {
+ interfaceName = (String) interfaceClassValue;
+ }
+ }
}
if (interfaceName == null && defaultInterfaceClass != GenericService.class) {
interfaceName = defaultInterfaceClass.getName();
diff --git a/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/schema/DubboBeanDefinitionParser.java b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/schema/DubboBeanDefinitionParser.java
index 85f2034..a28b497 100644
--- a/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/schema/DubboBeanDefinitionParser.java
+++ b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/schema/DubboBeanDefinitionParser.java
@@ -44,7 +44,6 @@ import org.springframework.beans.factory.support.ManagedMap;
import org.springframework.beans.factory.support.RootBeanDefinition;
import org.springframework.beans.factory.xml.BeanDefinitionParser;
import org.springframework.beans.factory.xml.ParserContext;
-import org.springframework.core.env.Environment;
import org.w3c.dom.Element;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
@@ -61,6 +60,7 @@ import java.util.Set;
import java.util.regex.Pattern;
import static org.apache.dubbo.common.constants.CommonConstants.HIDE_KEY_PREFIX;
+import static org.apache.dubbo.config.spring.util.SpringCompatUtils.getPropertyValue;
/**
* AbstractBeanDefinitionParser
@@ -76,6 +76,7 @@ public class DubboBeanDefinitionParser implements BeanDefinitionParser {
private static final String ONINVOKE = "oninvoke";
private static final String METHOD = "Method";
private static final String BEAN_NAME = "BEAN_NAME";
+ private static boolean resolvePlaceholdersEnabled = true;
private final Class<?> beanClass;
private static Map<String, Map<String, Class>> beanPropsCache = new HashMap<>();
@@ -247,11 +248,10 @@ public class DubboBeanDefinitionParser implements BeanDefinitionParser {
String generic = resolveAttribute(element, ReferenceAttributes.GENERIC, parserContext);
if (StringUtils.isBlank(generic) && consumerDefinition != null) {
// get generic from consumerConfig
- generic = (String) consumerDefinition.getPropertyValues().get(ReferenceAttributes.GENERIC);
+ generic = getPropertyValue(consumerDefinition.getPropertyValues(), ReferenceAttributes.GENERIC);
}
if (generic != null) {
- Environment environment = parserContext.getReaderContext().getEnvironment();
- generic = environment.resolvePlaceholders(generic);
+ generic = resolvePlaceholders(generic, parserContext);
beanDefinition.getPropertyValues().add(ReferenceAttributes.GENERIC, generic);
}
beanDefinition.setAttribute(ReferenceAttributes.INTERFACE_NAME, interfaceName);
@@ -513,6 +513,13 @@ public class DubboBeanDefinitionParser implements BeanDefinitionParser {
}
private static String resolvePlaceholders(String str, ParserContext parserContext) {
- return parserContext.getReaderContext().getEnvironment().resolveRequiredPlaceholders(str);
+ if (resolvePlaceholdersEnabled) {
+ try {
+ return parserContext.getReaderContext().getEnvironment().resolveRequiredPlaceholders(str);
+ } catch (NoSuchMethodError e) {
+ resolvePlaceholdersEnabled = false;
+ }
+ }
+ return str;
}
}
diff --git a/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/util/DubboBeanUtils.java b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/util/DubboBeanUtils.java
index 169af09..72f2177 100644
--- a/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/util/DubboBeanUtils.java
+++ b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/util/DubboBeanUtils.java
@@ -117,7 +117,7 @@ public interface DubboBeanUtils {
}
/**
- * Register some beans later
+ * Register a placeholder configurer beans if not exists.
* Call this method in BeanDefinitionRegistryPostProcessor,
* in order to enable the registered BeanFactoryPostProcessor bean to be loaded and executed.
* @see DubboInfraBeanRegisterPostProcessor
@@ -125,7 +125,7 @@ public interface DubboBeanUtils {
* @param beanFactory
* @param registry
*/
- static void registerBeansIfNotExists(ConfigurableListableBeanFactory beanFactory, BeanDefinitionRegistry registry) {
+ static void registerPlaceholderConfigurerBeanIfNotExists(ConfigurableListableBeanFactory beanFactory, BeanDefinitionRegistry registry) {
// Auto register a PropertyPlaceholderConfigurer bean to resolve placeholders with Spring Environment PropertySources
// when loading dubbo xml config with @ImportResource
if (!checkBeanExists(beanFactory, PropertySourcesPlaceholderConfigurer.class)) {
diff --git a/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/util/SpringCompatUtils.java b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/util/SpringCompatUtils.java
new file mode 100644
index 0000000..9faed82
--- /dev/null
+++ b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/util/SpringCompatUtils.java
@@ -0,0 +1,124 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.config.spring.util;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.springframework.beans.PropertyValue;
+import org.springframework.beans.PropertyValues;
+import org.springframework.beans.factory.annotation.AnnotatedBeanDefinition;
+import org.springframework.core.type.MethodMetadata;
+import org.springframework.core.type.StandardMethodMetadata;
+
+import java.lang.reflect.Method;
+import java.lang.reflect.ParameterizedType;
+import java.lang.reflect.Type;
+
+/**
+ * Spring Compatibility Utils for spring 3.x/4.x/5.x
+ */
+public class SpringCompatUtils {
+
+ private static volatile Boolean factoryMethodMetadataEnabled = null;
+
+ private static final Log logger = LogFactory.getLog(SpringCompatUtils.class);
+
+ public static <T> T getPropertyValue(PropertyValues pvs, String propertyName) {
+ PropertyValue pv = pvs.getPropertyValue(propertyName);
+ return (pv != null ? (T) pv.getValue() : null);
+ }
+
+ public static boolean isFactoryMethodMetadataEnabled() {
+ if (factoryMethodMetadataEnabled == null) {
+ try {
+ //check AnnotatedBeanDefinition.getFactoryMethodMetadata() since spring 4.1
+ AnnotatedBeanDefinition.class.getMethod("getFactoryMethodMetadata");
+
+ // check MethodMetadata.getReturnTypeName() since spring 4.2
+ MethodMetadata.class.getMethod("getReturnTypeName");
+
+ factoryMethodMetadataEnabled = true;
+ } catch (NoSuchMethodException e) {
+ factoryMethodMetadataEnabled = false;
+ }
+ }
+ return factoryMethodMetadataEnabled;
+ }
+
+ public static String getFactoryMethodReturnType(AnnotatedBeanDefinition annotatedBeanDefinition) {
+ try {
+ if (isFactoryMethodMetadataEnabled()) {
+ MethodMetadata factoryMethodMetadata = annotatedBeanDefinition.getFactoryMethodMetadata();
+ return factoryMethodMetadata != null ? factoryMethodMetadata.getReturnTypeName() : null;
+ } else {
+ Object source = annotatedBeanDefinition.getSource();
+ if (source instanceof StandardMethodMetadata) {
+ StandardMethodMetadata methodMetadata = (StandardMethodMetadata) source;
+ Method introspectedMethod = methodMetadata.getIntrospectedMethod();
+ if (introspectedMethod != null) {
+ return introspectedMethod.getReturnType().getName();
+ }
+ }
+ }
+ } catch (Throwable e) {
+ if (logger.isInfoEnabled()) {
+ logger.info("get return type of AnnotatedBeanDefinition failed", e);
+ }
+ }
+ return null;
+ }
+
+ public static MethodMetadata getFactoryMethodMetadata(AnnotatedBeanDefinition annotatedBeanDefinition) {
+ if (isFactoryMethodMetadataEnabled()) {
+ return annotatedBeanDefinition.getFactoryMethodMetadata();
+ } else {
+ Object source = annotatedBeanDefinition.getSource();
+ if (source instanceof StandardMethodMetadata) {
+ return (MethodMetadata) source;
+ }
+ return null;
+ }
+ }
+
+ /**
+ * Get the generic type of return type of the method.
+ *
+ * <pre>
+ * Source method:
+ * ReferenceBean<DemoService> demoService()
+ *
+ * Result: DemoService.class
+ * </pre>
+ *
+ * @param factoryMethodMetadata
+ * @return
+ */
+ public static Class getGenericTypeOfReturnType(MethodMetadata factoryMethodMetadata) {
+ if (factoryMethodMetadata instanceof StandardMethodMetadata) {
+ Method introspectedMethod = ((StandardMethodMetadata) factoryMethodMetadata).getIntrospectedMethod();
+ Type returnType = introspectedMethod.getGenericReturnType();
+ if (returnType instanceof ParameterizedType) {
+ ParameterizedType parameterizedType = (ParameterizedType) returnType;
+ Type actualTypeArgument = parameterizedType.getActualTypeArguments()[0];
+ if (actualTypeArgument instanceof Class) {
+ return (Class) actualTypeArgument;
+ }
+ }
+ }
+ return null;
+ }
+}
diff --git a/dubbo-spring-boot/dubbo-spring-boot-compatible/autoconfigure/src/main/java/org/apache/dubbo/spring/boot/beans/factory/config/ServiceBeanIdConflictProcessor.java b/dubbo-spring-boot/dubbo-spring-boot-compatible/autoconfigure/src/main/java/org/apache/dubbo/spring/boot/beans/factory/config/ServiceBeanIdConflictProcessor.java
index b6bf04b..77e0625 100644
--- a/dubbo-spring-boot/dubbo-spring-boot-compatible/autoconfigure/src/main/java/org/apache/dubbo/spring/boot/beans/factory/config/ServiceBeanIdConflictProcessor.java
+++ b/dubbo-spring-boot/dubbo-spring-boot-compatible/autoconfigure/src/main/java/org/apache/dubbo/spring/boot/beans/factory/config/ServiceBeanIdConflictProcessor.java
@@ -19,6 +19,7 @@ package org.apache.dubbo.spring.boot.beans.factory.config;
import org.apache.dubbo.config.ServiceConfig;
import org.apache.dubbo.config.spring.ServiceBean;
+import org.apache.dubbo.config.spring.reference.ReferenceAttributes;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.support.MergedBeanDefinitionPostProcessor;
@@ -33,6 +34,7 @@ import java.util.Map;
import java.util.Objects;
import java.util.Set;
+import static org.apache.dubbo.config.spring.util.SpringCompatUtils.getPropertyValue;
import static org.springframework.util.ClassUtils.getUserClass;
import static org.springframework.util.ClassUtils.isAssignable;
@@ -64,7 +66,8 @@ public class ServiceBeanIdConflictProcessor implements MergedBeanDefinitionPostP
// Get raw bean type
Class<?> rawBeanType = getUserClass(beanType);
if (isAssignable(ServiceConfig.class, rawBeanType)) { // ServiceConfig type or sub-type
- String interfaceName = (String) beanDefinition.getPropertyValues().get("interface");
+ String interfaceName = getPropertyValue(beanDefinition.getPropertyValues(), ReferenceAttributes.INTERFACE);
+
String mappedBeanName = interfaceNamesToBeanNames.putIfAbsent(interfaceName, beanName);
// If mapped bean name exists and does not equal current bean name
if (mappedBeanName != null && !mappedBeanName.equals(beanName)) {
diff --git a/dubbo-test/dubbo-test-common/pom.xml b/dubbo-test/dubbo-test-common/pom.xml
new file mode 100644
index 0000000..9c52951
--- /dev/null
+++ b/dubbo-test/dubbo-test-common/pom.xml
@@ -0,0 +1,61 @@
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <parent>
+ <artifactId>dubbo-test</artifactId>
+ <groupId>org.apache.dubbo</groupId>
+ <version>${revision}</version>
+ <relativePath>../pom.xml</relativePath>
+ </parent>
+ <modelVersion>4.0.0</modelVersion>
+
+ <artifactId>dubbo-test-common</artifactId>
+
+ <properties>
+ <maven.compiler.source>8</maven.compiler.source>
+ <maven.compiler.target>8</maven.compiler.target>
+ <skip_maven_deploy>true</skip_maven_deploy>
+ </properties>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.apache.zookeeper</groupId>
+ <artifactId>zookeeper</artifactId>
+ <exclusions>
+ <exclusion>
+ <groupId>org.slf4j</groupId>
+ <artifactId>slf4j-log4j12</artifactId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+
+ <dependency>
+ <groupId>org.apache.dubbo</groupId>
+ <artifactId>dubbo-common</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.dubbo</groupId>
+ <artifactId>dubbo-rpc-api</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.dubbo</groupId>
+ <artifactId>dubbo-rpc-rest</artifactId>
+ </dependency>
+ </dependencies>
+</project>
diff --git a/dubbo-test/dubbo-test-common/src/main/java/org/apache/dubbo/test/common/EmbeddedZooKeeper.java b/dubbo-test/dubbo-test-common/src/main/java/org/apache/dubbo/test/common/EmbeddedZooKeeper.java
new file mode 100644
index 0000000..e91755a
--- /dev/null
+++ b/dubbo-test/dubbo-test-common/src/main/java/org/apache/dubbo/test/common/EmbeddedZooKeeper.java
@@ -0,0 +1,244 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.test.common;
+
+import org.apache.dubbo.common.utils.NetUtils;
+import org.apache.zookeeper.server.ServerConfig;
+import org.apache.zookeeper.server.ZooKeeperServerMain;
+import org.apache.zookeeper.server.quorum.QuorumPeerConfig;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.File;
+import java.lang.reflect.Method;
+import java.util.Properties;
+import java.util.UUID;
+
+/**
+ * from: https://github.com/spring-projects/spring-xd/blob/v1.3.1.RELEASE/spring-xd-dirt/src/main/java/org/springframework/xd/dirt/zookeeper/ZooKeeperUtils.java
+ * <p>
+ * Helper class to start an embedded instance of standalone (non clustered) ZooKeeper.
+ * <p>
+ * NOTE: at least an external standalone server (if not an ensemble) are recommended, even for
+ * {@link org.springframework.xd.dirt.server.singlenode.SingleNodeApplication}
+ *
+ * @author Patrick Peralta
+ * @author Mark Fisher
+ * @author David Turanski
+ */
+public class EmbeddedZooKeeper {
+
+ /**
+ * Logger.
+ */
+ private static final Logger logger = LoggerFactory.getLogger(EmbeddedZooKeeper.class);
+
+ /**
+ * ZooKeeper client port. This will be determined dynamically upon startup.
+ */
+ private final int clientPort;
+
+ /**
+ * Whether to auto-start. Default is true.
+ */
+ private boolean autoStartup = true;
+
+ /**
+ * Lifecycle phase. Default is 0.
+ */
+ private int phase = 0;
+
+ /**
+ * Thread for running the ZooKeeper server.
+ */
+ private volatile Thread zkServerThread;
+
+ /**
+ * ZooKeeper server.
+ */
+ private volatile ZooKeeperServerMain zkServer;
+
+ /**
+ * {@link ErrorHandler} to be invoked if an Exception is thrown from the ZooKeeper server thread.
+ */
+ private ErrorHandler errorHandler;
+
+ private boolean daemon = true;
+
+ /**
+ * Construct an EmbeddedZooKeeper with a random port.
+ */
+ public EmbeddedZooKeeper() {
+ // clientPort = SocketUtils.findAvailableTcpPort();
+ clientPort = NetUtils.getAvailablePort();
+ }
+
+ /**
+ * Construct an EmbeddedZooKeeper with the provided port.
+ *
+ * @param clientPort port for ZooKeeper server to bind to
+ */
+ public EmbeddedZooKeeper(int clientPort, boolean daemon) {
+ this.clientPort = clientPort;
+ this.daemon = daemon;
+ }
+
+ /**
+ * Returns the port that clients should use to connect to this embedded server.
+ *
+ * @return dynamically determined client port
+ */
+ public int getClientPort() {
+ return this.clientPort;
+ }
+
+ /**
+ * Specify whether to start automatically. Default is true.
+ *
+ * @param autoStartup whether to start automatically
+ */
+ public void setAutoStartup(boolean autoStartup) {
+ this.autoStartup = autoStartup;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean isAutoStartup() {
+ return this.autoStartup;
+ }
+
+ /**
+ * Specify the lifecycle phase for the embedded server.
+ *
+ * @param phase the lifecycle phase
+ */
+ public void setPhase(int phase) {
+ this.phase = phase;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public int getPhase() {
+ return this.phase;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean isRunning() {
+ return (zkServerThread != null);
+ }
+
+ /**
+ * Start the ZooKeeper server in a background thread.
+ * <p>
+ * Register an error handler via {@link #setErrorHandler} in order to handle
+ * any exceptions thrown during startup or execution.
+ */
+ public synchronized void start() {
+ if (zkServerThread == null) {
+ zkServerThread = new Thread(new ServerRunnable(), "ZooKeeper Server Starter");
+ zkServerThread.setDaemon(daemon);
+ zkServerThread.start();
+ }
+ }
+
+ /**
+ * Shutdown the ZooKeeper server.
+ */
+ public synchronized void stop() {
+ if (zkServerThread != null) {
+ // The shutdown method is protected...thus this hack to invoke it.
+ // This will log an exception on shutdown; see
+ // https://issues.apache.org/jira/browse/ZOOKEEPER-1873 for details.
+ try {
+ Method shutdown = ZooKeeperServerMain.class.getDeclaredMethod("shutdown");
+ shutdown.setAccessible(true);
+ shutdown.invoke(zkServer);
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+
+ // It is expected that the thread will exit after
+ // the server is shutdown; this will block until
+ // the shutdown is complete.
+ try {
+ zkServerThread.join(5000);
+ zkServerThread = null;
+ } catch (InterruptedException e) {
+ Thread.currentThread().interrupt();
+ logger.warn("Interrupted while waiting for embedded ZooKeeper to exit");
+ // abandoning zk thread
+ zkServerThread = null;
+ }
+ }
+ }
+
+ /**
+ * Stop the server if running and invoke the callback when complete.
+ */
+ public void stop(Runnable callback) {
+ stop();
+ callback.run();
+ }
+
+ /**
+ * Provide an {@link ErrorHandler} to be invoked if an Exception is thrown from the ZooKeeper server thread. If none
+ * is provided, only error-level logging will occur.
+ *
+ * @param errorHandler the {@link ErrorHandler} to be invoked
+ */
+ public void setErrorHandler(ErrorHandler errorHandler) {
+ this.errorHandler = errorHandler;
+ }
+
+ /**
+ * Runnable implementation that starts the ZooKeeper server.
+ */
+ private class ServerRunnable implements Runnable {
+
+ @Override
+ public void run() {
+ try {
+ Properties properties = new Properties();
+ File file = new File(System.getProperty("java.io.tmpdir")
+ + File.separator + UUID.randomUUID());
+ file.deleteOnExit();
+ properties.setProperty("dataDir", file.getAbsolutePath());
+ properties.setProperty("clientPort", String.valueOf(clientPort));
+
+ QuorumPeerConfig quorumPeerConfig = new QuorumPeerConfig();
+ quorumPeerConfig.parseProperties(properties);
+
+ zkServer = new ZooKeeperServerMain();
+ ServerConfig configuration = new ServerConfig();
+ configuration.readFrom(quorumPeerConfig);
+
+ zkServer.runFromConfig(configuration);
+ } catch (Exception e) {
+ if (errorHandler != null) {
+ errorHandler.handleError(e);
+ } else {
+ logger.error("Exception running embedded ZooKeeper", e);
+ }
+ }
+ }
+ }
+
+}
diff --git a/dubbo-test/dubbo-test-common/src/main/java/org/apache/dubbo/test/common/ErrorHandler.java b/dubbo-test/dubbo-test-common/src/main/java/org/apache/dubbo/test/common/ErrorHandler.java
new file mode 100644
index 0000000..b44ff13
--- /dev/null
+++ b/dubbo-test/dubbo-test-common/src/main/java/org/apache/dubbo/test/common/ErrorHandler.java
@@ -0,0 +1,27 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.test.common;
+
+@FunctionalInterface
+public interface ErrorHandler {
+
+ /**
+ * Handle the given error, possibly rethrowing it as a fatal exception.
+ */
+ void handleError(Throwable t);
+
+}
diff --git a/dubbo-test/dubbo-test-common/src/main/java/org/apache/dubbo/test/common/SysProps.java b/dubbo-test/dubbo-test-common/src/main/java/org/apache/dubbo/test/common/SysProps.java
new file mode 100644
index 0000000..dac5edd
--- /dev/null
+++ b/dubbo-test/dubbo-test-common/src/main/java/org/apache/dubbo/test/common/SysProps.java
@@ -0,0 +1,45 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.test.common;
+
+import java.util.LinkedHashMap;
+import java.util.Map;
+
+/**
+ * Use to set and clear System property
+ */
+public class SysProps {
+
+ private static Map<String, String> map = new LinkedHashMap<String, String>();
+
+ public static void reset() {
+ map.clear();
+ }
+
+ public static void setProperty(String key, String value) {
+ map.put(key, value);
+ System.setProperty(key, value);
+ }
+
+ public static void clear() {
+ for (String key : map.keySet()) {
+ System.clearProperty(key);
+ }
+ reset();
+ }
+
+}
diff --git a/dubbo-test/dubbo-test-common/src/main/java/org/apache/dubbo/test/common/ZooKeeperServer.java b/dubbo-test/dubbo-test-common/src/main/java/org/apache/dubbo/test/common/ZooKeeperServer.java
new file mode 100644
index 0000000..ba34753
--- /dev/null
+++ b/dubbo-test/dubbo-test-common/src/main/java/org/apache/dubbo/test/common/ZooKeeperServer.java
@@ -0,0 +1,43 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.test.common;
+
+public class ZooKeeperServer {
+
+ private static EmbeddedZooKeeper zookeeper1;
+ private static EmbeddedZooKeeper zookeeper2;
+
+ public static void start() {
+ if (zookeeper1 == null) {
+ zookeeper1 = new EmbeddedZooKeeper(2181, true);
+ zookeeper1.start();
+ }
+ if (zookeeper2 == null) {
+ zookeeper2 = new EmbeddedZooKeeper(2182, true);
+ zookeeper2.start();
+ }
+ }
+
+ public static void stop() {
+ if (zookeeper1 != null) {
+ zookeeper1.stop();
+ }
+ if (zookeeper2 != null) {
+ zookeeper2.stop();
+ }
+ }
+}
diff --git a/dubbo-test/dubbo-test-common/src/main/java/org/apache/dubbo/test/common/api/DemoService.java b/dubbo-test/dubbo-test-common/src/main/java/org/apache/dubbo/test/common/api/DemoService.java
new file mode 100644
index 0000000..9a5dfc1
--- /dev/null
+++ b/dubbo-test/dubbo-test-common/src/main/java/org/apache/dubbo/test/common/api/DemoService.java
@@ -0,0 +1,27 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.test.common.api;
+
+import java.util.concurrent.CompletableFuture;
+
+public interface DemoService {
+
+ String sayHello(String name);
+
+ CompletableFuture<String> sayHelloAsync(String name);
+
+}
diff --git a/dubbo-test/dubbo-test-common/src/main/java/org/apache/dubbo/test/common/api/GreetingService.java b/dubbo-test/dubbo-test-common/src/main/java/org/apache/dubbo/test/common/api/GreetingService.java
new file mode 100644
index 0000000..16df570
--- /dev/null
+++ b/dubbo-test/dubbo-test-common/src/main/java/org/apache/dubbo/test/common/api/GreetingService.java
@@ -0,0 +1,24 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.test.common.api;
+
+/**
+ *
+ */
+public interface GreetingService {
+ String hello();
+}
diff --git a/dubbo-test/dubbo-test-common/src/main/java/org/apache/dubbo/test/common/api/RestDemoService.java b/dubbo-test/dubbo-test-common/src/main/java/org/apache/dubbo/test/common/api/RestDemoService.java
new file mode 100644
index 0000000..809cd94
--- /dev/null
+++ b/dubbo-test/dubbo-test-common/src/main/java/org/apache/dubbo/test/common/api/RestDemoService.java
@@ -0,0 +1,45 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.test.common.api;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.GET;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.QueryParam;
+import javax.ws.rs.core.MediaType;
+
+
+@Path("/demoService")
+public interface RestDemoService {
+ @GET
+ @Path("/hello")
+ Integer hello(@QueryParam("a") Integer a, @QueryParam("b") Integer b);
+
+ @GET
+ @Path("/error")
+ String error();
+
+ @POST
+ @Path("/say")
+ @Consumes({MediaType.TEXT_PLAIN})
+ String sayHello(String name);
+
+ @GET
+ @Path("/getRemoteApplicationName")
+ String getRemoteApplicationName();
+}
diff --git a/dubbo-test/dubbo-test-common/src/main/java/org/apache/dubbo/test/common/impl/DemoServiceImpl.java b/dubbo-test/dubbo-test-common/src/main/java/org/apache/dubbo/test/common/impl/DemoServiceImpl.java
new file mode 100644
index 0000000..4b80d8b
--- /dev/null
+++ b/dubbo-test/dubbo-test-common/src/main/java/org/apache/dubbo/test/common/impl/DemoServiceImpl.java
@@ -0,0 +1,43 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.test.common.impl;
+
+import org.apache.dubbo.config.annotation.DubboService;
+import org.apache.dubbo.test.common.api.DemoService;
+
+import java.util.concurrent.CompletableFuture;
+
+@DubboService
+public class DemoServiceImpl implements DemoService {
+ @Override
+ public String sayHello(String name) {
+ return "Hello " + name;
+ }
+
+ @Override
+ public CompletableFuture<String> sayHelloAsync(String name) {
+ CompletableFuture<String> cf = CompletableFuture.supplyAsync(() -> {
+// try {
+// Thread.sleep(1000);
+// } catch (InterruptedException e) {
+// e.printStackTrace();
+// }
+ return "async result:" + name;
+ });
+ return cf;
+ }
+}
diff --git a/dubbo-test/dubbo-test-common/src/main/java/org/apache/dubbo/test/common/impl/GreetingServiceImpl.java b/dubbo-test/dubbo-test-common/src/main/java/org/apache/dubbo/test/common/impl/GreetingServiceImpl.java
new file mode 100644
index 0000000..0ad249a
--- /dev/null
+++ b/dubbo-test/dubbo-test-common/src/main/java/org/apache/dubbo/test/common/impl/GreetingServiceImpl.java
@@ -0,0 +1,30 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.test.common.impl;
+
+
+import org.apache.dubbo.test.common.api.GreetingService;
+
+/**
+ *
+ */
+public class GreetingServiceImpl implements GreetingService {
+ @Override
+ public String hello() {
+ return "Greetings!";
+ }
+}
diff --git a/dubbo-test/dubbo-test-common/src/main/java/org/apache/dubbo/test/common/impl/RestDemoServiceImpl.java b/dubbo-test/dubbo-test-common/src/main/java/org/apache/dubbo/test/common/impl/RestDemoServiceImpl.java
new file mode 100644
index 0000000..c863314
--- /dev/null
+++ b/dubbo-test/dubbo-test-common/src/main/java/org/apache/dubbo/test/common/impl/RestDemoServiceImpl.java
@@ -0,0 +1,58 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.test.common.impl;
+
+
+import org.apache.dubbo.rpc.RpcContext;
+import org.apache.dubbo.test.common.api.RestDemoService;
+
+import java.util.Map;
+
+public class RestDemoServiceImpl implements RestDemoService {
+ private static Map<String, Object> context;
+ private boolean called;
+
+ public String sayHello(String name) {
+ called = true;
+ return "Hello, " + name;
+ }
+
+
+ public boolean isCalled() {
+ return called;
+ }
+
+ @Override
+ public Integer hello(Integer a, Integer b) {
+ context = RpcContext.getServerAttachment().getObjectAttachments();
+ return a + b;
+ }
+
+ @Override
+ public String error() {
+ throw new RuntimeException();
+ }
+
+ public static Map<String, Object> getAttachments() {
+ return context;
+ }
+
+ @Override
+ public String getRemoteApplicationName() {
+ return RpcContext.getServiceContext().getRemoteApplicationName();
+ }
+}
diff --git a/dubbo-test/dubbo-test-spring/pom.xml b/dubbo-test/dubbo-test-spring/pom.xml
new file mode 100644
index 0000000..3e417d3
--- /dev/null
+++ b/dubbo-test/dubbo-test-spring/pom.xml
@@ -0,0 +1,170 @@
+<!--
+ 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.
+ -->
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <parent>
+ <artifactId>dubbo-test</artifactId>
+ <groupId>org.apache.dubbo</groupId>
+ <version>${revision}</version>
+ <relativePath>../pom.xml</relativePath>
+ </parent>
+ <modelVersion>4.0.0</modelVersion>
+
+ <artifactId>dubbo-test-spring</artifactId>
+
+ <properties>
+ <skip_maven_deploy>true</skip_maven_deploy>
+ <slf4j-log4j12.version>1.7.25</slf4j-log4j12.version>
+ <spring_version>3.2.18.RELEASE</spring_version>
+ <!--<spring_version>4.0.9.RELEASE</spring_version>-->
+ <!--<spring_version>4.1.9.RELEASE</spring_version>-->
+ <!--<spring_version>4.2.4.RELEASE</spring_version>-->
+ </properties>
+
+ <dependencyManagement>
+ <dependencies>
+ <dependency>
+ <groupId>org.springframework</groupId>
+ <artifactId>spring-framework-bom</artifactId>
+ <version>${spring_version}</version>
+ <type>pom</type>
+ <scope>import</scope>
+ </dependency>
+ </dependencies>
+ </dependencyManagement>
+
+ <dependencies>
+ <!-- test common -->
+ <dependency>
+ <groupId>org.apache.dubbo</groupId>
+ <artifactId>dubbo-test-common</artifactId>
+ <version>${project.parent.version}</version>
+ </dependency>
+
+ <!-- Dubbo -->
+ <dependency>
+ <groupId>org.apache.dubbo</groupId>
+ <artifactId>dubbo-registry-multicast</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.dubbo</groupId>
+ <artifactId>dubbo-registry-zookeeper</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.dubbo</groupId>
+ <artifactId>dubbo-registry-nacos</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>com.alibaba.nacos</groupId>
+ <artifactId>nacos-client</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.dubbo</groupId>
+ <artifactId>dubbo-configcenter-zookeeper</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.dubbo</groupId>
+ <artifactId>dubbo-configcenter-nacos</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.dubbo</groupId>
+ <artifactId>dubbo-metadata-report-zookeeper</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.dubbo</groupId>
+ <artifactId>dubbo-metadata-report-nacos</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.dubbo</groupId>
+ <artifactId>dubbo-rpc-dubbo</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.dubbo</groupId>
+ <artifactId>dubbo-rpc-rest</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.dubbo</groupId>
+ <artifactId>dubbo-config-spring</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.dubbo</groupId>
+ <artifactId>dubbo-remoting-netty4</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.dubbo</groupId>
+ <artifactId>dubbo-serialization-hessian2</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.dubbo</groupId>
+ <artifactId>dubbo-serialization-jdk</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>slf4j-api</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>slf4j-log4j12</artifactId>
+ <version>${slf4j-log4j12.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>log4j</groupId>
+ <artifactId>log4j</artifactId>
+ </dependency>
+
+
+ <!--JUnit Jupiter Engine to depend on the JUnit5 engine and JUnit 5 API -->
+ <dependency>
+ <groupId>org.junit.jupiter</groupId>
+ <artifactId>junit-jupiter-engine</artifactId>
+ <version>${junit_jupiter_version}</version>
+ <!--<scope>test</scope>-->
+ </dependency>
+ <dependency>
+ <groupId>org.junit.jupiter</groupId>
+ <artifactId>junit-jupiter-params</artifactId>
+ <version>${junit_jupiter_version}</version>
+ <!--<scope>test</scope>-->
+ </dependency>
+ <dependency>
+ <groupId>org.hamcrest</groupId>
+ <artifactId>hamcrest</artifactId>
+ <version>${hamcrest_version}</version>
+ <!--<scope>test</scope>-->
+ </dependency>
+ <dependency>
+ <groupId>org.mockito</groupId>
+ <artifactId>mockito-core</artifactId>
+ <version>${mockito_version}</version>
+ <!--<scope>test</scope>-->
+ </dependency>
+ <dependency>
+ <groupId>org.mockito</groupId>
+ <artifactId>mockito-inline</artifactId>
+ <version>${mockito_version}</version>
+ <!--<scope>test</scope>-->
+ </dependency>
+ <dependency>
+ <groupId>cglib</groupId>
+ <artifactId>cglib-nodep</artifactId>
+ <version>${cglib_version}</version>
+ <!--<scope>test</scope>-->
+ </dependency>
+ </dependencies>
+
+</project>
diff --git a/dubbo-test/dubbo-test-spring/src/main/java/org/apache/dubbo/test/spring/SpringAnnotationBeanTest.java b/dubbo-test/dubbo-test-spring/src/main/java/org/apache/dubbo/test/spring/SpringAnnotationBeanTest.java
new file mode 100644
index 0000000..d0cc44c
--- /dev/null
+++ b/dubbo-test/dubbo-test-spring/src/main/java/org/apache/dubbo/test/spring/SpringAnnotationBeanTest.java
@@ -0,0 +1,67 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.test.spring;
+
+import org.apache.dubbo.config.annotation.DubboReference;
+import org.apache.dubbo.config.bootstrap.DubboBootstrap;
+import org.apache.dubbo.config.spring.context.annotation.EnableDubbo;
+import org.apache.dubbo.test.common.ZooKeeperServer;
+import org.apache.dubbo.test.common.api.DemoService;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.Test;
+import org.springframework.context.annotation.AnnotationConfigApplicationContext;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.PropertySource;
+
+public class SpringAnnotationBeanTest {
+ @BeforeAll
+ public static void beforeAll() {
+ ZooKeeperServer.start();
+ DubboBootstrap.reset();
+ }
+
+ @Test
+ public void test() {
+ AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(TestConfiguration.class);
+ TestService testService = applicationContext.getBean(TestService.class);
+ testService.test();
+ }
+
+ @EnableDubbo(scanBasePackages = "org.apache.dubbo.test.common.impl")
+ @Configuration
+ @PropertySource("/demo-app.properties")
+ static class TestConfiguration {
+
+ @Bean
+ public TestService testService() {
+ return new TestService();
+ }
+ }
+
+ static class TestService {
+
+ @DubboReference
+ private DemoService demoService;
+
+ public void test() {
+ String result = demoService.sayHello("dubbo");
+ Assertions.assertEquals("Hello dubbo", result);
+ }
+ }
+}
diff --git a/dubbo-test/dubbo-test-spring/src/main/java/org/apache/dubbo/test/spring/SpringJavaConfigBeanTest.java b/dubbo-test/dubbo-test-spring/src/main/java/org/apache/dubbo/test/spring/SpringJavaConfigBeanTest.java
new file mode 100644
index 0000000..bcd2e5d
--- /dev/null
+++ b/dubbo-test/dubbo-test-spring/src/main/java/org/apache/dubbo/test/spring/SpringJavaConfigBeanTest.java
@@ -0,0 +1,186 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.test.spring;
+
+import org.apache.dubbo.config.ApplicationConfig;
+import org.apache.dubbo.config.ConsumerConfig;
+import org.apache.dubbo.config.ProtocolConfig;
+import org.apache.dubbo.config.ReferenceConfig;
+import org.apache.dubbo.config.RegistryConfig;
+import org.apache.dubbo.config.annotation.DubboReference;
+import org.apache.dubbo.config.annotation.DubboService;
+import org.apache.dubbo.config.bootstrap.DubboBootstrap;
+import org.apache.dubbo.config.context.ConfigManager;
+import org.apache.dubbo.config.spring.ReferenceBean;
+import org.apache.dubbo.config.spring.context.annotation.EnableDubbo;
+import org.apache.dubbo.rpc.Constants;
+import org.apache.dubbo.rpc.model.ApplicationModel;
+import org.apache.dubbo.test.common.SysProps;
+import org.apache.dubbo.test.common.ZooKeeperServer;
+import org.apache.dubbo.test.common.api.DemoService;
+import org.apache.dubbo.test.common.impl.DemoServiceImpl;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.springframework.context.annotation.AnnotationConfigApplicationContext;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+import java.util.Collection;
+import java.util.Map;
+
+public class SpringJavaConfigBeanTest {
+
+ private static final String MY_PROTOCOL_ID = "myProtocol";
+ private static final String MY_REGISTRY_ID = "my-registry";
+
+ @BeforeAll
+ public static void beforeAll() {
+ ZooKeeperServer.start();
+ DubboBootstrap.reset();
+ }
+
+ @BeforeEach
+ public void beforeEach() {
+ DubboBootstrap.reset();
+ }
+
+ @AfterEach
+ public void afterEach() {
+ SysProps.clear();
+ }
+
+ @Test
+ public void testBean() {
+
+ SysProps.setProperty("dubbo.application.owner", "Tom");
+ SysProps.setProperty("dubbo.application.qos-enable", "false");
+ SysProps.setProperty("dubbo.protocol.name", "dubbo");
+ SysProps.setProperty("dubbo.protocol.port", "2346");
+ String registryAddress = "zookeeper://127.0.0.1:2181";
+ SysProps.setProperty("dubbo.registry.address", registryAddress);
+ SysProps.setProperty("dubbo.provider.group", "test");
+
+ AnnotationConfigApplicationContext consumerContext = new AnnotationConfigApplicationContext(
+ TestConfiguration.class, ConsumerConfiguration.class, ProviderConfiguration.class);
+ try {
+ consumerContext.start();
+
+ ConfigManager configManager = ApplicationModel.getConfigManager();
+ ApplicationConfig application = configManager.getApplication().get();
+ Assertions.assertEquals(false, application.getQosEnable());
+ Assertions.assertEquals("Tom", application.getOwner());
+
+ RegistryConfig registry = configManager.getRegistry(MY_REGISTRY_ID).get();
+ Assertions.assertEquals(registryAddress, registry.getAddress());
+
+ Collection<ProtocolConfig> protocols = configManager.getProtocols();
+ Assertions.assertEquals(1, protocols.size());
+ ProtocolConfig protocolConfig = protocols.iterator().next();
+ Assertions.assertEquals("dubbo", protocolConfig.getName());
+ Assertions.assertEquals(2346, protocolConfig.getPort());
+ Assertions.assertEquals(MY_PROTOCOL_ID, protocolConfig.getId());
+
+ ConsumerConfig consumerConfig = configManager.getDefaultConsumer().get();
+ Assertions.assertEquals(1000, consumerConfig.getTimeout());
+ Assertions.assertEquals("demo", consumerConfig.getGroup());
+ Assertions.assertEquals(false, consumerConfig.isCheck());
+ Assertions.assertEquals(2, consumerConfig.getRetries());
+
+ Map<String, ReferenceBean> referenceBeanMap = consumerContext.getBeansOfType(ReferenceBean.class);
+ Assertions.assertEquals(1, referenceBeanMap.size());
+ ReferenceBean referenceBean = referenceBeanMap.get("&demoService");
+ Assertions.assertNotNull(referenceBean);
+ ReferenceConfig referenceConfig = referenceBean.getReferenceConfig();
+ // use consumer's attributes as default value
+ Assertions.assertEquals(consumerConfig.getTimeout(), referenceConfig.getTimeout());
+ Assertions.assertEquals(consumerConfig.getGroup(), referenceConfig.getGroup());
+ // consumer cannot override reference's attribute
+ Assertions.assertEquals(5, referenceConfig.getRetries());
+
+ DemoService referProxy = (DemoService) referenceConfig.get();
+ Assertions.assertTrue( referProxy instanceof DemoService);
+ String result = referProxy.sayHello("dubbo");
+ Assertions.assertEquals("Hello dubbo", result);
+
+ } finally {
+ consumerContext.close();
+ }
+
+ }
+
+
+ @EnableDubbo(scanBasePackages = "")
+ @Configuration
+ static class TestConfiguration {
+
+ @Bean(name = "dubbo-demo-application")
+ public ApplicationConfig applicationConfig() {
+ ApplicationConfig applicationConfig = new ApplicationConfig();
+ applicationConfig.setName("dubbo-demo-application");
+ return applicationConfig;
+ }
+
+ @Bean(name = MY_PROTOCOL_ID)
+ public ProtocolConfig protocolConfig() {
+ ProtocolConfig protocolConfig = new ProtocolConfig();
+ protocolConfig.setName("rest");
+ protocolConfig.setPort(1234);
+ return protocolConfig;
+ }
+
+ @Bean(name = MY_REGISTRY_ID)
+ public RegistryConfig registryConfig() {
+ RegistryConfig registryConfig = new RegistryConfig();
+ registryConfig.setAddress("N/A");
+ return registryConfig;
+ }
+
+ @Bean
+ public ConsumerConfig consumerConfig() {
+ ConsumerConfig consumer = new ConsumerConfig();
+ consumer.setTimeout(1000);
+ consumer.setGroup("demo");
+ consumer.setCheck(false);
+ consumer.setRetries(2);
+ return consumer;
+ }
+ }
+
+ @Configuration
+ static class ConsumerConfiguration {
+
+ @Bean
+ @DubboReference(scope = Constants.SCOPE_LOCAL, retries = 5)
+ public ReferenceBean<DemoService> demoService() {
+ return new ReferenceBean<>();
+ }
+
+ }
+
+ @Configuration
+ static class ProviderConfiguration {
+
+ @Bean
+ @DubboService(group = "demo")
+ public DemoService demoServiceImpl() {
+ return new DemoServiceImpl();
+ }
+ }
+}
diff --git a/dubbo-test/dubbo-test-spring/src/main/java/org/apache/dubbo/test/spring/SpringXmlConfigTest.java b/dubbo-test/dubbo-test-spring/src/main/java/org/apache/dubbo/test/spring/SpringXmlConfigTest.java
new file mode 100644
index 0000000..492ee1a
--- /dev/null
+++ b/dubbo-test/dubbo-test-spring/src/main/java/org/apache/dubbo/test/spring/SpringXmlConfigTest.java
@@ -0,0 +1,66 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.test.spring;
+
+import org.apache.dubbo.config.bootstrap.DubboBootstrap;
+import org.apache.dubbo.test.common.SysProps;
+import org.apache.dubbo.test.common.ZooKeeperServer;
+import org.apache.dubbo.test.common.api.DemoService;
+import org.apache.dubbo.test.common.api.GreetingService;
+import org.apache.dubbo.test.common.api.RestDemoService;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.Test;
+import org.springframework.context.support.ClassPathXmlApplicationContext;
+
+import static org.apache.dubbo.common.constants.CommonConstants.SHUTDOWN_WAIT_KEY;
+
+public class SpringXmlConfigTest {
+
+ @BeforeAll
+ public static void beforeAll() {
+ ZooKeeperServer.start();
+ DubboBootstrap.reset();
+ }
+
+ @Test
+ public void test() {
+ SysProps.setProperty(SHUTDOWN_WAIT_KEY, "2000");
+ ClassPathXmlApplicationContext applicationContext = null;
+ try {
+ applicationContext = new ClassPathXmlApplicationContext("/spring/dubbo-demo.xml");
+
+ GreetingService greetingService = applicationContext.getBean("greetingService", GreetingService.class);
+ String greeting = greetingService.hello();
+ Assertions.assertEquals(greeting, "Greetings!");
+
+ DemoService demoService = applicationContext.getBean("demoService", DemoService.class);
+ String sayHelloResult = demoService.sayHello("dubbo");
+ Assertions.assertTrue(sayHelloResult.startsWith("Hello dubbo"), sayHelloResult);
+
+ RestDemoService restDemoService = applicationContext.getBean("restDemoService", RestDemoService.class);
+ String resetHelloResult = restDemoService.sayHello("dubbo");
+ Assertions.assertEquals("Hello, dubbo", resetHelloResult);
+ } finally {
+ SysProps.clear();
+ if (applicationContext != null) {
+ applicationContext.close();
+ }
+ }
+
+ }
+}
diff --git a/dubbo-test/dubbo-test-spring/src/main/resources/demo-app.properties b/dubbo-test/dubbo-test-spring/src/main/resources/demo-app.properties
new file mode 100644
index 0000000..f5bfdff
--- /dev/null
+++ b/dubbo-test/dubbo-test-spring/src/main/resources/demo-app.properties
@@ -0,0 +1,11 @@
+
+dubbo.application.name=demo-app
+
+dubbo.registry.address=zookeeper://127.0.0.1:2181?registry-type=service
+
+dubbo.config-center.address=zookeeper://127.0.0.1:2181
+
+dubbo.metadata-report.address=zookeeper://127.0.0.1:2181
+
+dubbo.protocols.dubbo.port=-1
+
diff --git a/dubbo-test/dubbo-test-spring/src/main/resources/log4j.properties b/dubbo-test/dubbo-test-spring/src/main/resources/log4j.properties
new file mode 100644
index 0000000..8de4c4f
--- /dev/null
+++ b/dubbo-test/dubbo-test-spring/src/main/resources/log4j.properties
@@ -0,0 +1,7 @@
+###set log levels###
+log4j.rootLogger=info, stdout
+###output to the console###
+log4j.appender.stdout=org.apache.log4j.ConsoleAppender
+log4j.appender.stdout.Target=System.out
+log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
+log4j.appender.stdout.layout.ConversionPattern=[%d{dd/MM/yy HH:mm:ss:SSS z}] %t %5p %c{2}: %m%n
diff --git a/dubbo-test/dubbo-test-spring/src/main/resources/spring/dubbo-demo.xml b/dubbo-test/dubbo-test-spring/src/main/resources/spring/dubbo-demo.xml
new file mode 100644
index 0000000..05392da
--- /dev/null
+++ b/dubbo-test/dubbo-test-spring/src/main/resources/spring/dubbo-demo.xml
@@ -0,0 +1,53 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ 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.
+ -->
+<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns:dubbo="http://dubbo.apache.org/schema/dubbo"
+ xmlns="http://www.springframework.org/schema/beans"
+ xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
+ http://dubbo.apache.org/schema/dubbo http://dubbo.apache.org/schema/dubbo/dubbo.xsd">
+
+ <dubbo:application name="demo-app" />
+
+ <dubbo:config-center address="zookeeper://127.0.0.1:2181"/>
+ <dubbo:metadata-report address="zookeeper://127.0.0.1:2181"/>
+ <dubbo:registry address="zookeeper://127.0.0.1:2181?registry-type=service"/>
+
+ <dubbo:protocol name="dubbo" port="-1"/>
+ <dubbo:protocol name="rest" port="-1"/>
+
+ <bean id="demoServiceImpl" class="org.apache.dubbo.test.common.impl.DemoServiceImpl"/>
+ <bean id="greetingServiceImpl" class="org.apache.dubbo.test.common.impl.GreetingServiceImpl"/>
+ <bean id="restDemoServiceImpl" class="org.apache.dubbo.test.common.impl.RestDemoServiceImpl"/>
+
+ <dubbo:service interface="org.apache.dubbo.test.common.api.DemoService" timeout="3000" ref="demoServiceImpl" protocol="dubbo"/>
+ <dubbo:service version="1.0.0" group="greeting" timeout="5000" interface="org.apache.dubbo.test.common.api.GreetingService"
+ ref="greetingServiceImpl" protocol="dubbo"/>
+ <dubbo:service version="1.0.0" timeout="5000" interface="org.apache.dubbo.test.common.api.RestDemoService"
+ ref="restDemoServiceImpl" protocol="rest"/>
+
+ <!-- references -->
+ <dubbo:consumer check="false" scope="remote" />
+ <dubbo:reference id="demoService" scope="local"
+ interface="org.apache.dubbo.test.common.api.DemoService"/>
+
+ <dubbo:reference id="greetingService" version="1.0.0" group="greeting"
+ interface="org.apache.dubbo.test.common.api.GreetingService"/>
+
+ <dubbo:reference id="restDemoService" version="1.0.0" protocol="rest"
+ interface="org.apache.dubbo.test.common.api.RestDemoService"/>
+</beans>
diff --git a/dubbo-test/dubbo-test-spring3.2/pom.xml b/dubbo-test/dubbo-test-spring3.2/pom.xml
new file mode 100644
index 0000000..c349bdd
--- /dev/null
+++ b/dubbo-test/dubbo-test-spring3.2/pom.xml
@@ -0,0 +1,70 @@
+<!--
+ 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.
+ -->
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <parent>
+ <artifactId>dubbo-test</artifactId>
+ <groupId>org.apache.dubbo</groupId>
+ <version>${revision}</version>
+ <relativePath>../pom.xml</relativePath>
+ </parent>
+ <modelVersion>4.0.0</modelVersion>
+
+ <artifactId>dubbo-test-spring3.2</artifactId>
+
+ <properties>
+ <skip_maven_deploy>true</skip_maven_deploy>
+ <spring_version>3.2.18.RELEASE</spring_version>
+ </properties>
+
+ <dependencyManagement>
+ <dependencies>
+ <dependency>
+ <groupId>org.springframework</groupId>
+ <artifactId>spring-framework-bom</artifactId>
+ <version>${spring_version}</version>
+ <type>pom</type>
+ <scope>import</scope>
+ </dependency>
+ </dependencies>
+ </dependencyManagement>
+
+ <dependencies>
+ <!-- spring test -->
+ <dependency>
+ <groupId>org.apache.dubbo</groupId>
+ <artifactId>dubbo-test-spring</artifactId>
+ <version>${project.parent.version}</version>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-surefire-plugin</artifactId>
+ <configuration>
+ <dependenciesToScan>
+ <dependency>org.apache.dubbo:dubbo-test-spring</dependency>
+ </dependenciesToScan>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+</project>
diff --git a/dubbo-test/dubbo-test-spring4.1/pom.xml b/dubbo-test/dubbo-test-spring4.1/pom.xml
new file mode 100644
index 0000000..942e055
--- /dev/null
+++ b/dubbo-test/dubbo-test-spring4.1/pom.xml
@@ -0,0 +1,70 @@
+<!--
+ 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.
+ -->
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <parent>
+ <artifactId>dubbo-test</artifactId>
+ <groupId>org.apache.dubbo</groupId>
+ <version>${revision}</version>
+ <relativePath>../pom.xml</relativePath>
+ </parent>
+ <modelVersion>4.0.0</modelVersion>
+
+ <artifactId>dubbo-test-spring4.1</artifactId>
+
+ <properties>
+ <skip_maven_deploy>true</skip_maven_deploy>
+ <spring_version>4.1.9.RELEASE</spring_version>
+ </properties>
+
+ <dependencyManagement>
+ <dependencies>
+ <dependency>
+ <groupId>org.springframework</groupId>
+ <artifactId>spring-framework-bom</artifactId>
+ <version>${spring_version}</version>
+ <type>pom</type>
+ <scope>import</scope>
+ </dependency>
+ </dependencies>
+ </dependencyManagement>
+
+ <dependencies>
+ <!-- spring test -->
+ <dependency>
+ <groupId>org.apache.dubbo</groupId>
+ <artifactId>dubbo-test-spring</artifactId>
+ <version>${project.parent.version}</version>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-surefire-plugin</artifactId>
+ <configuration>
+ <dependenciesToScan>
+ <dependency>org.apache.dubbo:dubbo-test-spring</dependency>
+ </dependenciesToScan>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+</project>
diff --git a/dubbo-test/dubbo-test-spring4.2/pom.xml b/dubbo-test/dubbo-test-spring4.2/pom.xml
new file mode 100644
index 0000000..e53c596
--- /dev/null
+++ b/dubbo-test/dubbo-test-spring4.2/pom.xml
@@ -0,0 +1,70 @@
+<!--
+ 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.
+ -->
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <parent>
+ <artifactId>dubbo-test</artifactId>
+ <groupId>org.apache.dubbo</groupId>
+ <version>${revision}</version>
+ <relativePath>../pom.xml</relativePath>
+ </parent>
+ <modelVersion>4.0.0</modelVersion>
+
+ <artifactId>dubbo-test-spring4.2</artifactId>
+
+ <properties>
+ <skip_maven_deploy>true</skip_maven_deploy>
+ <spring_version>4.2.4.RELEASE</spring_version>
+ </properties>
+
+ <dependencyManagement>
+ <dependencies>
+ <dependency>
+ <groupId>org.springframework</groupId>
+ <artifactId>spring-framework-bom</artifactId>
+ <version>${spring_version}</version>
+ <type>pom</type>
+ <scope>import</scope>
+ </dependency>
+ </dependencies>
+ </dependencyManagement>
+
+ <dependencies>
+ <!-- spring test -->
+ <dependency>
+ <groupId>org.apache.dubbo</groupId>
+ <artifactId>dubbo-test-spring</artifactId>
+ <version>${project.parent.version}</version>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-surefire-plugin</artifactId>
+ <configuration>
+ <dependenciesToScan>
+ <dependency>org.apache.dubbo:dubbo-test-spring</dependency>
+ </dependenciesToScan>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+</project>
diff --git a/dubbo-test/pom.xml b/dubbo-test/pom.xml
new file mode 100644
index 0000000..bc6fee2
--- /dev/null
+++ b/dubbo-test/pom.xml
@@ -0,0 +1,56 @@
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <parent>
+ <groupId>org.apache.dubbo</groupId>
+ <artifactId>dubbo-parent</artifactId>
+ <version>${revision}</version>
+ <relativePath>../pom.xml</relativePath>
+ </parent>
+ <modelVersion>4.0.0</modelVersion>
+ <artifactId>dubbo-test</artifactId>
+ <packaging>pom</packaging>
+
+ <modules>
+ <module>dubbo-test-common</module>
+ <module>dubbo-test-spring</module>
+ <module>dubbo-test-spring3.2</module>
+ <module>dubbo-test-spring4.1</module>
+ <module>dubbo-test-spring4.2</module>
+ </modules>
+
+ <properties>
+ <maven.compiler.source>8</maven.compiler.source>
+ <maven.compiler.target>8</maven.compiler.target>
+ <skip_maven_deploy>true</skip_maven_deploy>
+ </properties>
+
+ <dependencyManagement>
+ <dependencies>
+ <dependency>
+ <groupId>org.apache.dubbo</groupId>
+ <artifactId>dubbo-bom</artifactId>
+ <version>${project.parent.version}</version>
+ <type>pom</type>
+ <scope>import</scope>
+ </dependency>
+ </dependencies>
+ </dependencyManagement>
+
+</project>
diff --git a/pom.xml b/pom.xml
index a0ed38e..034699f 100644
--- a/pom.xml
+++ b/pom.xml
@@ -153,6 +153,7 @@
<module>dubbo-build-tools</module>
<module>dubbo-spring-boot</module>
<module>dubbo-native</module>
+ <module>dubbo-test</module>
</modules>
<dependencyManagement>
@@ -691,6 +692,7 @@
<plugins>
<!-- keep surefire and failsafe in sync -->
<plugin>
+ <groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>${maven_surefire_version}</version>
</plugin>