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/07/08 14:04:56 UTC
[dubbo] branch 3.0 updated: [3.0] Improve property placeholder
resolving of reference bean (#8187)
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 b260d45 [3.0] Improve property placeholder resolving of reference bean (#8187)
b260d45 is described below
commit b260d45a69354ebba5c112ce7a54b2f58ffef75a
Author: Gong Dewei <ky...@qq.com>
AuthorDate: Thu Jul 8 22:04:43 2021 +0800
[3.0] Improve property placeholder resolving of reference bean (#8187)
* Improve property placeholder resolving of config bean
* Fix tests
* register ReferenceAnnotationBeanPostProcessor as BeanPostProcessor early, improve reference key and reference name mapping
* get ReferenceAnnotationBeanPostProcessor from beanFactory, fix tests
* polish code
* Improve tests
---
.../dubbo/config/bootstrap/DubboBootstrap.java | 1 +
.../ReferenceAnnotationBeanPostProcessor.java | 73 +++++-----
.../DubboInfraBeanRegisterPostProcessor.java | 13 +-
.../spring/reference/ReferenceBeanManager.java | 51 ++++---
.../spring/reference/ReferenceBeanSupport.java | 37 ++---
.../dubbo/config/spring/util/DubboBeanUtils.java | 52 +++----
.../ReferenceAnnotationBeanPostProcessorTest.java | 29 ++--
.../SpringBootMultipleConfigPropsTest.java | 2 +
.../consumer/PropertyConfigurerTest.java | 3 +-
.../consumer2/PropertySourcesConfigurerTest.java | 4 +-
.../consumer3/PropertySourcesInJavaConfigTest.java | 160 +++++++++++++++++++++
.../propertyconfigurer/consumer3/app.properties | 4 +
.../consumer3/dubbo-consumer.xml | 36 +++++
.../config/spring/reference/ReferenceKeyTest.java | 17 ++-
.../LocalCallMultipleReferenceAnnotationsTest.java | 9 +-
.../DubboRelaxedBinding2AutoConfigurationTest.java | 12 +-
.../endpoint/metadata/AbstractDubboMetadata.java | 4 +-
.../CompatibleDubboAutoConfigurationTest.java | 7 +-
...ubboAutoConfigurationTestWithoutProperties.java | 6 +-
19 files changed, 386 insertions(+), 134 deletions(-)
diff --git a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/bootstrap/DubboBootstrap.java b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/bootstrap/DubboBootstrap.java
index 5fe0196..9b0f063 100644
--- a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/bootstrap/DubboBootstrap.java
+++ b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/bootstrap/DubboBootstrap.java
@@ -1528,6 +1528,7 @@ public class DubboBootstrap {
private void destroyMetadataReports() {
AbstractMetadataReportFactory.destroy();
+ MetadataReportInstance.reset();
ExtensionLoader.resetExtensionLoader(MetadataReportFactory.class);
}
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 0c4d8b4..5b2df1c 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
@@ -150,10 +150,14 @@ public class ReferenceAnnotationBeanPostProcessor extends AbstractAnnotationBean
} catch (BeansException e) {
throw e;
} catch (Exception e) {
- throw new RuntimeException("Prepare dubbo reference injection element failed", e);
+ throw new IllegalStateException("Prepare dubbo reference injection element failed", e);
}
}
}
+
+ // 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);
}
/**
@@ -273,18 +277,13 @@ public class ReferenceAnnotationBeanPostProcessor extends AbstractAnnotationBean
try {
prepareInjection(metadata);
} catch (Exception e) {
- throw new RuntimeException("Prepare dubbo reference injection element failed", e);
+ throw new IllegalStateException("Prepare dubbo reference injection element failed", e);
}
}
}
}
@Override
- public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
- return super.postProcessBeforeInitialization(bean, beanName);
- }
-
- @Override
public PropertyValues postProcessPropertyValues(
PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeansException {
@@ -362,12 +361,20 @@ public class ReferenceAnnotationBeanPostProcessor extends AbstractAnnotationBean
}
// check reference key
- String referenceKey = ReferenceBeanSupport.generateReferenceKey(attributes, applicationContext.getEnvironment());
+ String referenceKey = ReferenceBeanSupport.generateReferenceKey(attributes, applicationContext);
- // check registered reference beans in referenceBeanManager
- List<String> registeredReferenceBeanNames = referenceBeanManager.getByKey(referenceKey);
- if (registeredReferenceBeanNames.contains(referenceBeanName)) {
- return referenceBeanName;
+ // find reference bean name by reference key
+ List<String> registeredReferenceBeanNames = referenceBeanManager.getBeanNamesByKey(referenceKey);
+ if (registeredReferenceBeanNames.size() > 0) {
+ // found same name and reference key
+ if (registeredReferenceBeanNames.contains(referenceBeanName)) {
+ return referenceBeanName;
+ }
+// else if (renameable) {
+// // reference key matched, but difference bean name
+// return registeredReferenceBeanNames.get(0);
+// }
+ // specify bean name by id attribute, it will register alias later
}
//check bean definition
@@ -379,7 +386,7 @@ public class ReferenceAnnotationBeanPostProcessor extends AbstractAnnotationBean
if (isReferenceBean(prevBeanDefinition)) {
//check reference key
- String prevReferenceKey = ReferenceBeanSupport.generateReferenceKey(prevBeanDefinition, applicationContext.getEnvironment());
+ String prevReferenceKey = ReferenceBeanSupport.generateReferenceKey(prevBeanDefinition, applicationContext);
if (StringUtils.isEquals(prevReferenceKey, referenceKey)) {
//found matched dubbo reference bean, ignore register
return referenceBeanName;
@@ -389,27 +396,23 @@ public class ReferenceAnnotationBeanPostProcessor extends AbstractAnnotationBean
Assert.notNull(prevBeanDefinition, "The interface class of ReferenceBean is not initialized");
prevBeanType = prevInterfaceClass.getName();
prevBeanDesc = referenceBeanName + "[" + prevReferenceKey + "]";
+
//check bean type
- if (StringUtils.isEquals(prevBeanType, interfaceName)) {
- throw new BeanCreationException("Already exists another reference bean with the same bean name and type but difference attributes. " +
- "In order to avoid injection confusion, please modify the name of one of the beans: " +
- "prev: " + prevBeanDesc + ", new: " + newBeanDesc+". "+checkLocation);
- }
- } else {
- //check bean type
- if (StringUtils.isEquals(prevBeanType, interfaceName)) {
- throw new BeanCreationException("Already exists another bean definition with the same bean name and type. " +
- "In order to avoid injection confusion, please modify the name of one of the beans: " +
- "prev: " + prevBeanDesc + ", new: " + newBeanDesc+". "+checkLocation);
- }
+ // If two reference beans are the same type and name, then other class injection them by type or name are confusion.
+ // Let it go, Spring find candidate bean will check it
+// if (StringUtils.isEquals(prevBeanType, interfaceName)) {
+// throw new BeanCreationException("Already exists another reference bean with the same bean name and type but difference attributes. " +
+// "In order to avoid injection confusion later, please modify the name of one of the beans: " +
+// "prev: " + prevBeanDesc + ", new: " + newBeanDesc+". "+checkLocation);
+// }
}
// bean name from attribute 'id' or java-config bean, cannot be renamed
if (!renameable) {
- throw new BeanCreationException("Already exists another bean definition with the same bean name, " +
- "but cannot rename the reference bean name (specify the id attribute or java-config bean), " +
- "please modify the name of one of the beans: " +
- "prev: " + prevBeanDesc + ", new: " + newBeanDesc+". "+checkLocation);
+ throw new BeanCreationException("Already exists another bean definition with the same bean name [" + referenceBeanName + "], " +
+ "but cannot rename the reference bean name (specify the id attribute or java-config bean), " +
+ "please modify the name of one of the beans: " +
+ "prev: " + prevBeanDesc + ", new: " + newBeanDesc + ". " + checkLocation);
}
// the prev bean type is different, rename the new reference bean
@@ -421,17 +424,18 @@ public class ReferenceAnnotationBeanPostProcessor extends AbstractAnnotationBean
}
newBeanDesc = newReferenceBeanName + "[" + referenceKey + "]";
- logger.warn("Already exists another bean definition with the same bean name but difference type, " +
- "rename dubbo reference bean to: " + newReferenceBeanName + ". " +
- "It is recommended to modify the name of one of the beans to avoid injection problems. " +
- "prev: " + prevBeanDesc + ", new: " + newBeanDesc+". "+checkLocation);
+ logger.warn("Already exists another bean definition with the same bean name [" + referenceBeanName + "], " +
+ "rename dubbo reference bean to [" + newReferenceBeanName + "]. " +
+ "It is recommended to modify the name of one of the beans to avoid injection problems. " +
+ "prev: " + prevBeanDesc + ", new: " + newBeanDesc + ". " + checkLocation);
referenceBeanName = newReferenceBeanName;
}
attributes.put(ReferenceAttributes.ID, referenceBeanName);
- // If registered matched reference before, add alias
+ // If registered matched reference before, just register alias
if (registeredReferenceBeanNames.size() > 0) {
beanDefinitionRegistry.registerAlias(registeredReferenceBeanNames.get(0), referenceBeanName);
+ referenceBeanManager.registerReferenceKeyAndBeanName(referenceKey, referenceBeanName);
return referenceBeanName;
}
@@ -460,6 +464,7 @@ public class ReferenceAnnotationBeanPostProcessor extends AbstractAnnotationBean
beanDefinition.setAttribute(Constants.OBJECT_TYPE_ATTRIBUTE, interfaceClass);
beanDefinitionRegistry.registerBeanDefinition(referenceBeanName, beanDefinition);
+ referenceBeanManager.registerReferenceKeyAndBeanName(referenceKey, referenceBeanName);
logger.info("Register dubbo reference bean: "+referenceBeanName+" = "+referenceKey+" at "+member);
return referenceBeanName;
}
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 927317e..a16bd30 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
@@ -37,7 +37,8 @@ import java.util.SortedMap;
* Register some infrastructure beans if not exists.
* This post-processor MUST impl BeanDefinitionRegistryPostProcessor,
* in order to enable the registered BeanFactoryPostProcessor bean to be loaded and executed.
- * @see org.springframework.context.support.PostProcessorRegistrationDelegate#invokeBeanFactoryPostProcessors(org.springframework.beans.factory.config.ConfigurableListableBeanFactory, java.util.List)
+ * @see org.springframework.context.support.PostProcessorRegistrationDelegate#invokeBeanFactoryPostProcessors(
+ * org.springframework.beans.factory.config.ConfigurableListableBeanFactory, java.util.List)
*/
public class DubboInfraBeanRegisterPostProcessor implements BeanDefinitionRegistryPostProcessor, ApplicationContextAware {
@@ -56,7 +57,15 @@ public class DubboInfraBeanRegisterPostProcessor implements BeanDefinitionRegist
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
- DubboBeanUtils.registerBeansIfNotExists(registry);
+
+ // 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 ConfigManager singleton
beanFactory.registerSingleton(ConfigManager.BEAN_NAME, ApplicationModel.getConfigManager());
diff --git a/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/reference/ReferenceBeanManager.java b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/reference/ReferenceBeanManager.java
index 73b9e91..e5b04aa 100644
--- a/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/reference/ReferenceBeanManager.java
+++ b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/reference/ReferenceBeanManager.java
@@ -25,11 +25,11 @@ import org.apache.dubbo.config.spring.ReferenceBean;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
-import org.springframework.core.env.PropertyResolver;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
+import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
@@ -38,40 +38,44 @@ import java.util.concurrent.ConcurrentHashMap;
public class ReferenceBeanManager implements ApplicationContextAware {
public static final String BEAN_NAME = "dubboReferenceBeanManager";
private final Log logger = LogFactory.getLog(getClass());
- //reference bean id/name -> ReferenceBean
- private Map<String, ReferenceBean> referenceIdMap = new ConcurrentHashMap<>();
- //reference key -> [ reference bean names ]
+ //reference key -> reference bean names
private Map<String, List<String>> referenceKeyMap = new ConcurrentHashMap<>();
+ // reference alias -> reference bean name
+ private Map<String, String> referenceAliasMap = new ConcurrentHashMap<>();
+
+ //reference bean name -> ReferenceBean
+ private Map<String, ReferenceBean> referenceBeanMap = new ConcurrentHashMap<>();
+
//reference key -> ReferenceConfig instance
private Map<String, ReferenceConfig> referenceConfigMap = new ConcurrentHashMap<>();
+
private ApplicationContext applicationContext;
private volatile boolean initialized = false;
public void addReference(ReferenceBean referenceBean) throws Exception {
String referenceBeanName = referenceBean.getId();
Assert.notEmptyString(referenceBeanName, "The id of ReferenceBean cannot be empty");
- PropertyResolver propertyResolver = applicationContext.getEnvironment();
if (!initialized) {
//TODO add issue url to describe early initialization
logger.warn("Early initialize reference bean before DubboConfigInitializationPostProcessor," +
" the BeanPostProcessor has not been loaded at this time, which may cause abnormalities in some components (such as seata): " +
- referenceBeanName + " = " + ReferenceBeanSupport.generateReferenceKey(referenceBean, propertyResolver));
+ referenceBeanName + " = " + ReferenceBeanSupport.generateReferenceKey(referenceBean, applicationContext));
}
- String referenceKey = ReferenceBeanSupport.generateReferenceKey(referenceBean, propertyResolver);
- ReferenceBean oldReferenceBean = referenceIdMap.get(referenceBeanName);
+ String referenceKey = ReferenceBeanSupport.generateReferenceKey(referenceBean, applicationContext);
+ ReferenceBean oldReferenceBean = referenceBeanMap.get(referenceBeanName);
if (oldReferenceBean != null) {
if (referenceBean != oldReferenceBean) {
- String oldReferenceKey = ReferenceBeanSupport.generateReferenceKey(oldReferenceBean, propertyResolver);
+ String oldReferenceKey = ReferenceBeanSupport.generateReferenceKey(oldReferenceBean, applicationContext);
throw new IllegalStateException("Found duplicated ReferenceBean with id: " + referenceBeanName +
", old: " + oldReferenceKey + ", new: " + referenceKey);
}
return;
}
- referenceIdMap.put(referenceBeanName, referenceBean);
+ referenceBeanMap.put(referenceBeanName, referenceBean);
//save cache, map reference key to referenceBeanName
this.registerReferenceKeyAndBeanName(referenceKey, referenceBeanName);
@@ -81,20 +85,31 @@ public class ReferenceBeanManager implements ApplicationContextAware {
}
}
- public void registerReferenceKeyAndBeanName(String referenceKey, String referenceBeanName) {
- referenceKeyMap.getOrDefault(referenceKey, new ArrayList<>()).add(referenceBeanName);
+ public void registerReferenceKeyAndBeanName(String referenceKey, String referenceBeanNameOrAlias) {
+ List<String> list = referenceKeyMap.computeIfAbsent(referenceKey, (key) -> new ArrayList<>());
+ if (!list.contains(referenceBeanNameOrAlias)) {
+ list.add(referenceBeanNameOrAlias);
+ // register bean name as alias
+ referenceAliasMap.put(referenceBeanNameOrAlias, list.get(0));
+ }
+ }
+
+ public ReferenceBean getById(String referenceBeanNameOrAlias) {
+ String referenceBeanName = transformName(referenceBeanNameOrAlias);
+ return referenceBeanMap.get(referenceBeanName);
}
- public ReferenceBean getById(String key) {
- return referenceIdMap.get(key);
+ // convert reference name/alias to referenceBeanName
+ private String transformName(String referenceBeanNameOrAlias) {
+ return referenceAliasMap.getOrDefault(referenceBeanNameOrAlias, referenceBeanNameOrAlias);
}
- public List<String> getByKey(String key) {
- return Collections.unmodifiableList(referenceKeyMap.getOrDefault(key, new ArrayList<>()));
+ public List<String> getBeanNamesByKey(String key) {
+ return Collections.unmodifiableList(referenceKeyMap.getOrDefault(key, Collections.EMPTY_LIST));
}
public Collection<ReferenceBean> getReferences() {
- return referenceIdMap.values();
+ return new HashSet<>(referenceBeanMap.values());
}
@Override
@@ -135,7 +150,7 @@ public class ReferenceBeanManager implements ApplicationContextAware {
// TOTO check same unique service name but difference reference key (means difference attributes).
// reference key
- String referenceKey = ReferenceBeanSupport.generateReferenceKey(referenceBean, applicationContext.getEnvironment());
+ String referenceKey = ReferenceBeanSupport.generateReferenceKey(referenceBean, applicationContext);
ReferenceConfig referenceConfig = referenceConfigMap.get(referenceKey);
if (referenceConfig == null) {
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 3ba683b..678b5db 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
@@ -28,10 +28,11 @@ import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.BeanDefinitionHolder;
import org.springframework.beans.factory.config.RuntimeBeanReference;
import org.springframework.beans.factory.config.TypedStringValue;
+import org.springframework.beans.factory.support.AbstractBeanFactory;
import org.springframework.beans.factory.support.ManagedList;
import org.springframework.beans.factory.support.ManagedMap;
+import org.springframework.context.ApplicationContext;
import org.springframework.core.annotation.AnnotationAttributes;
-import org.springframework.core.env.PropertyResolver;
import org.springframework.util.ObjectUtils;
import java.lang.annotation.Annotation;
@@ -70,7 +71,8 @@ public class ReferenceBeanSupport {
//reset generic value
String generic = String.valueOf(defaultInterfaceClass == GenericService.class);
- String oldGeneric = attributes.containsValue(ReferenceAttributes.GENERIC) ? String.valueOf(attributes.get(ReferenceAttributes.GENERIC)) : "false";
+ String oldGeneric = attributes.containsValue(ReferenceAttributes.GENERIC) ?
+ String.valueOf(attributes.get(ReferenceAttributes.GENERIC)) : "false";
if (!StringUtils.isEquals(oldGeneric, generic)) {
attributes.put(ReferenceAttributes.GENERIC, generic);
}
@@ -86,7 +88,7 @@ public class ReferenceBeanSupport {
}
- public static String generateReferenceKey(Map<String, Object> attributes, PropertyResolver propertyResolver) {
+ public static String generateReferenceKey(Map<String, Object> attributes, ApplicationContext applicationContext) {
String interfaceClass = (String) attributes.get(ReferenceAttributes.INTERFACE);
Assert.notEmptyString(interfaceClass, "No interface class or name found from attributes");
@@ -108,7 +110,9 @@ public class ReferenceBeanSupport {
//sort attributes keys
List<String> sortedAttrKeys = new ArrayList<>(attributes.keySet());
Collections.sort(sortedAttrKeys);
- List<String> ignoredAttrs = Arrays.asList(ReferenceAttributes.ID, ReferenceAttributes.GROUP, ReferenceAttributes.VERSION, ReferenceAttributes.INTERFACE, ReferenceAttributes.INTERFACE_NAME, ReferenceAttributes.INTERFACE_CLASS);
+ List<String> ignoredAttrs = Arrays.asList(ReferenceAttributes.ID, ReferenceAttributes.GROUP,
+ ReferenceAttributes.VERSION, ReferenceAttributes.INTERFACE, ReferenceAttributes.INTERFACE_NAME,
+ ReferenceAttributes.INTERFACE_CLASS);
for (String key : sortedAttrKeys) {
if (ignoredAttrs.contains(key)) {
continue;
@@ -130,18 +134,19 @@ public class ReferenceBeanSupport {
}
String referenceKey = beanNameBuilder.toString();
- if (propertyResolver != null) {
- referenceKey = propertyResolver.resolveRequiredPlaceholders(referenceKey);
+ if (applicationContext != null) {
+ // resolve placeholder with Spring Environment
+ referenceKey = applicationContext.getEnvironment().resolvePlaceholders(referenceKey);
+ // resolve placeholder with Spring BeanFactory ( using PropertyResourceConfigurer/PropertySourcesPlaceholderConfigurer )
+ referenceKey = ((AbstractBeanFactory) applicationContext.getAutowireCapableBeanFactory()).resolveEmbeddedValue(referenceKey);
}
+ // The property placeholder maybe not resolved if is early init
+ // if (referenceKey != null && referenceKey.contains("${")) {
+ // throw new IllegalStateException("Reference key contains unresolved placeholders ${..} : " + referenceKey);
+ // }
return referenceKey;
}
-// public static void verifyReferenceKey(String referenceKey) {
-// if (referenceKey != null && referenceKey.contains("${")) {
-// throw new IllegalStateException("Reference key contains unresolved placeholders ${..}");
-// }
-// }
-
private static String convertToString(String key, Object obj) {
if (obj == null) {
return null;
@@ -226,12 +231,12 @@ public class ReferenceBeanSupport {
return map;
}
- public static String generateReferenceKey(ReferenceBean referenceBean, PropertyResolver propertyResolver) {
- return generateReferenceKey(getReferenceAttributes(referenceBean), propertyResolver);
+ public static String generateReferenceKey(ReferenceBean referenceBean, ApplicationContext applicationContext) {
+ return generateReferenceKey(getReferenceAttributes(referenceBean), applicationContext);
}
- public static String generateReferenceKey(BeanDefinition beanDefinition, PropertyResolver propertyResolver) {
- return generateReferenceKey(getReferenceAttributes(beanDefinition), propertyResolver);
+ public static String generateReferenceKey(BeanDefinition beanDefinition, ApplicationContext applicationContext) {
+ return generateReferenceKey(getReferenceAttributes(beanDefinition), applicationContext);
}
public static Map<String, Object> getReferenceAttributes(ReferenceBean referenceBean) {
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 126fa5e..b5a1a0c 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
@@ -28,15 +28,17 @@ import org.apache.dubbo.config.spring.context.DubboBootstrapApplicationListener;
import org.apache.dubbo.config.spring.context.DubboInfraBeanRegisterPostProcessor;
import org.apache.dubbo.config.spring.context.DubboLifecycleComponentApplicationListener;
import org.springframework.beans.factory.config.BeanDefinition;
-import org.springframework.beans.factory.config.PropertyPlaceholderConfigurer;
+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.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.RootBeanDefinition;
+import org.springframework.context.ApplicationContext;
import org.springframework.context.support.PropertySourcesPlaceholderConfigurer;
import java.util.HashMap;
import java.util.Map;
-import java.util.Objects;
/**
* Dubbo Bean utilities class
@@ -126,33 +128,27 @@ public interface DubboBeanUtils {
* in order to enable the registered BeanFactoryPostProcessor bean to be loaded and executed.
* @see DubboInfraBeanRegisterPostProcessor
* @see org.springframework.context.support.PostProcessorRegistrationDelegate#invokeBeanFactoryPostProcessors(org.springframework.beans.factory.config.ConfigurableListableBeanFactory, java.util.List)
+ * @param beanFactory
* @param registry
*/
- static void registerBeansIfNotExists(BeanDefinitionRegistry registry) {
- // Resolve ${...} placeholders of bean definition with Spring Environment
-
- // If PropertyPlaceholderConfigurer already exists, PropertySourcesPlaceholderConfigurer cannot be registered.
- // When both of them exist, a conflict will occur, and an exception will be thrown when encountering an unresolved placeholder
-
- if (!checkBeanExists(registry, PropertyPlaceholderConfigurer.class)) {
+ static void registerBeansIfNotExists(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)) {
Map<String, Object> propertySourcesPlaceholderPropertyValues = new HashMap<>();
- // to make sure the default PropertySourcesPlaceholderConfigurer's priority is higher than PropertyPlaceholderConfigurer
- propertySourcesPlaceholderPropertyValues.put("order", 0);
- registerBeanDefinitionIfNotExists(registry, PropertySourcesPlaceholderConfigurer.class.getName(),
+ propertySourcesPlaceholderPropertyValues.put("ignoreUnresolvablePlaceholders", true);
+
+ registerBeanDefinition(registry, PropertySourcesPlaceholderConfigurer.class.getName(),
PropertySourcesPlaceholderConfigurer.class, propertySourcesPlaceholderPropertyValues);
}
}
- static boolean registerBeanDefinitionIfNotExists(BeanDefinitionRegistry registry, String beanName,
+ static boolean registerBeanDefinition(BeanDefinitionRegistry registry, String beanName,
Class<?> beanClass, Map<String, Object> extraPropertyValues) {
if (registry.containsBeanDefinition(beanName)) {
return false;
}
- if (checkBeanExists(registry, beanClass)) {
- return false;
- }
-
BeanDefinition beanDefinition = BeanDefinitionBuilder.genericBeanDefinition(beanClass).getBeanDefinition();
if (extraPropertyValues != null) {
for (Map.Entry<String, Object> entry : extraPropertyValues.entrySet()) {
@@ -161,19 +157,25 @@ public interface DubboBeanUtils {
}
registry.registerBeanDefinition(beanName, beanDefinition);
-
return true;
}
- static boolean checkBeanExists(BeanDefinitionRegistry registry, Class<?> beanClass) {
- String[] candidates = registry.getBeanDefinitionNames();
- for (String candidate : candidates) {
- BeanDefinition beanDefinition = registry.getBeanDefinition(candidate);
- if (Objects.equals(beanDefinition.getBeanClassName(), beanClass.getName())) {
- return true;
+ static boolean checkBeanExists(ConfigurableListableBeanFactory beanFactory, Class<?> targetClass) {
+ String[] beanNames = beanFactory.getBeanNamesForType(targetClass, true, false);
+ return (beanNames != null && beanNames.length > 0);
+ }
+
+
+ static ReferenceAnnotationBeanPostProcessor getReferenceAnnotationBeanPostProcessor(AbstractBeanFactory beanFactory) {
+ for (BeanPostProcessor beanPostProcessor : beanFactory.getBeanPostProcessors()) {
+ if (beanPostProcessor instanceof ReferenceAnnotationBeanPostProcessor) {
+ return (ReferenceAnnotationBeanPostProcessor) beanPostProcessor;
}
}
- return false;
+ return null;
}
+ static ReferenceAnnotationBeanPostProcessor getReferenceAnnotationBeanPostProcessor(ApplicationContext applicationContext) {
+ return getReferenceAnnotationBeanPostProcessor((AbstractBeanFactory) applicationContext.getAutowireCapableBeanFactory());
+ }
}
diff --git a/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/beans/factory/annotation/ReferenceAnnotationBeanPostProcessorTest.java b/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/beans/factory/annotation/ReferenceAnnotationBeanPostProcessorTest.java
index ec301e6..8a040af 100644
--- a/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/beans/factory/annotation/ReferenceAnnotationBeanPostProcessorTest.java
+++ b/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/beans/factory/annotation/ReferenceAnnotationBeanPostProcessorTest.java
@@ -27,7 +27,7 @@ import org.apache.dubbo.config.spring.context.annotation.EnableDubbo;
import org.apache.dubbo.config.spring.reference.ReferenceBeanManager;
import org.apache.dubbo.config.spring.api.DemoService;
import org.apache.dubbo.config.spring.api.HelloService;
-import org.apache.dubbo.config.utils.ReferenceConfigCache;
+import org.apache.dubbo.config.spring.util.DubboBeanUtils;
import org.apache.dubbo.rpc.RpcContext;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
@@ -54,7 +54,6 @@ import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
-import static org.apache.dubbo.config.spring.beans.factory.annotation.ReferenceAnnotationBeanPostProcessor.BEAN_NAME;
import static org.springframework.test.annotation.DirtiesContext.ClassMode.AFTER_EACH_TEST_METHOD;
/**
@@ -141,11 +140,12 @@ public class ReferenceAnnotationBeanPostProcessorTest {
Assertions.assertNotNull(testBean.getDemoServiceFromParent());
Assertions.assertNotNull(testBean.getDemoService());
Assertions.assertNotNull(testBean.myDemoService);
- Assertions.assertEquals(4, demoServicesMap.size());
- Assertions.assertNotNull(demoServicesMap.get("demoServiceImpl"));
- Assertions.assertNotNull(demoServicesMap.get("myDemoService"));
- Assertions.assertNotNull(demoServicesMap.get("demoService"));
- Assertions.assertNotNull(demoServicesMap.get("demoServiceFromParent"));
+ Assertions.assertEquals(2, demoServicesMap.size());
+
+ Assertions.assertNotNull(context.getBean("demoServiceImpl"));
+ Assertions.assertNotNull(context.getBean("myDemoService"));
+ Assertions.assertNotNull(context.getBean("demoService"));
+ Assertions.assertNotNull(context.getBean("demoServiceFromParent"));
String callSuffix = AOP_SUFFIX + " from "+ NetUtils.getLocalHost() +":12345";
String localCallSuffix = AOP_SUFFIX + " from 127.0.0.1:0";
@@ -174,8 +174,7 @@ public class ReferenceAnnotationBeanPostProcessorTest {
@Test
public void testGetInjectedFieldReferenceBeanMap() {
- ReferenceAnnotationBeanPostProcessor beanPostProcessor = context.getBean(BEAN_NAME,
- ReferenceAnnotationBeanPostProcessor.class);
+ ReferenceAnnotationBeanPostProcessor beanPostProcessor = getReferenceAnnotationBeanPostProcessor();
Map<InjectionMetadata.InjectedElement, ReferenceBean<?>> referenceBeanMap =
beanPostProcessor.getInjectedFieldReferenceBeanMap();
@@ -201,11 +200,14 @@ public class ReferenceAnnotationBeanPostProcessorTest {
}
}
+ private ReferenceAnnotationBeanPostProcessor getReferenceAnnotationBeanPostProcessor() {
+ return DubboBeanUtils.getReferenceAnnotationBeanPostProcessor(context);
+ }
+
@Test
public void testGetInjectedMethodReferenceBeanMap() {
- ReferenceAnnotationBeanPostProcessor beanPostProcessor = context.getBean(BEAN_NAME,
- ReferenceAnnotationBeanPostProcessor.class);
+ ReferenceAnnotationBeanPostProcessor beanPostProcessor = getReferenceAnnotationBeanPostProcessor();
Map<InjectionMetadata.InjectedElement, ReferenceBean<?>> referenceBeanMap =
beanPostProcessor.getInjectedMethodReferenceBeanMap();
@@ -258,12 +260,12 @@ public class ReferenceAnnotationBeanPostProcessorTest {
Collection<ReferenceBean> referenceBeans = referenceBeanManager.getReferences();
- Assertions.assertEquals(5, referenceBeans.size());
+ Assertions.assertEquals(3, referenceBeans.size());
for (ReferenceBean referenceBean : referenceBeans) {
ReferenceConfig referenceConfig = referenceBean.getReferenceConfig();
Assertions.assertNotNull(referenceConfig);
- Assertions.assertNotNull(ReferenceConfigCache.getCache().get(referenceConfig));
+ Assertions.assertNotNull(referenceConfig.get());
}
ReferenceBean helloServiceReferenceBean = referenceBeanManager.getById("helloService");
@@ -275,6 +277,7 @@ public class ReferenceAnnotationBeanPostProcessorTest {
ReferenceBean demoServiceReferenceBean = referenceBeanManager.getById("demoService");
Assertions.assertEquals(demoServiceFromParentReferenceBean.getKey(), demoServiceReferenceBean.getKey());
Assertions.assertEquals(demoServiceFromParentReferenceBean.getReferenceConfig(), demoServiceReferenceBean.getReferenceConfig());
+ Assertions.assertSame(demoServiceFromParentReferenceBean, demoServiceReferenceBean);
ReferenceBean helloService2Bean = referenceBeanManager.getById("helloService2");
Assertions.assertNotNull(helloService2Bean);
diff --git a/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/boot/configprops/SpringBootMultipleConfigPropsTest.java b/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/boot/configprops/SpringBootMultipleConfigPropsTest.java
index 2179306..2f2d293 100644
--- a/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/boot/configprops/SpringBootMultipleConfigPropsTest.java
+++ b/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/boot/configprops/SpringBootMultipleConfigPropsTest.java
@@ -26,6 +26,7 @@ import org.apache.dubbo.config.MonitorConfig;
import org.apache.dubbo.config.ProtocolConfig;
import org.apache.dubbo.config.ProviderConfig;
import org.apache.dubbo.config.RegistryConfig;
+import org.apache.dubbo.config.bootstrap.DubboBootstrap;
import org.apache.dubbo.config.context.ConfigManager;
import org.apache.dubbo.config.spring.ZooKeeperServer;
import org.apache.dubbo.config.spring.context.annotation.EnableDubbo;
@@ -68,6 +69,7 @@ public class SpringBootMultipleConfigPropsTest {
@BeforeAll
public static void setUp() {
ZooKeeperServer.start();
+ DubboBootstrap.reset();
}
@Autowired
diff --git a/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/propertyconfigurer/consumer/PropertyConfigurerTest.java b/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/propertyconfigurer/consumer/PropertyConfigurerTest.java
index 081def1..9916b80 100644
--- a/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/propertyconfigurer/consumer/PropertyConfigurerTest.java
+++ b/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/propertyconfigurer/consumer/PropertyConfigurerTest.java
@@ -48,7 +48,6 @@ public class PropertyConfigurerTest {
providerContext.start();
// clear config manager
- //ApplicationModel.getConfigManager().clear();
DubboBootstrap.reset(false);
try {
@@ -56,6 +55,7 @@ public class PropertyConfigurerTest {
} catch (InterruptedException e) {
}
+ // Resolve placeholder by PropertyPlaceholderConfigurer in dubbo-consumer.xml, without import property source.
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(ConsumerConfiguration.class);
context.start();
@@ -76,7 +76,6 @@ public class PropertyConfigurerTest {
@EnableDubbo(scanBasePackages = "org.apache.dubbo.config.spring.propertyconfigurer.consumer")
@ComponentScan(value = {"org.apache.dubbo.config.spring.propertyconfigurer.consumer"})
@ImportResource("classpath:/org/apache/dubbo/config/spring/propertyconfigurer/consumer/dubbo-consumer.xml")
- @PropertySource("classpath:/org/apache/dubbo/config/spring/propertyconfigurer/consumer/app.properties")
static class ConsumerConfiguration {
@Bean
public DemoBeanFactoryPostProcessor bizBeanFactoryPostProcessor(HelloService service) {
diff --git a/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/propertyconfigurer/consumer2/PropertySourcesConfigurerTest.java b/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/propertyconfigurer/consumer2/PropertySourcesConfigurerTest.java
index 40e0dfd..89b5298 100644
--- a/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/propertyconfigurer/consumer2/PropertySourcesConfigurerTest.java
+++ b/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/propertyconfigurer/consumer2/PropertySourcesConfigurerTest.java
@@ -21,7 +21,6 @@ import org.apache.dubbo.config.spring.ZooKeeperServer;
import org.apache.dubbo.config.spring.api.HelloService;
import org.apache.dubbo.config.spring.context.annotation.EnableDubbo;
import org.apache.dubbo.config.spring.propertyconfigurer.consumer.DemoBeanFactoryPostProcessor;
-import org.apache.dubbo.rpc.model.ApplicationModel;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
@@ -30,7 +29,6 @@ import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.ImportResource;
-import org.springframework.context.annotation.PropertySource;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class PropertySourcesConfigurerTest {
@@ -56,6 +54,7 @@ public class PropertySourcesConfigurerTest {
// reset config
DubboBootstrap.reset(false);
+ // Resolve placeholder by PropertySourcesPlaceholderConfigurer in dubbo-consumer.xml, without import property source.
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(ConsumerConfiguration.class);
try {
context.start();
@@ -76,7 +75,6 @@ public class PropertySourcesConfigurerTest {
@EnableDubbo(scanBasePackages = "org.apache.dubbo.config.spring.propertyconfigurer.consumer2")
@ComponentScan(value = {"org.apache.dubbo.config.spring.propertyconfigurer.consumer2"})
@ImportResource("classpath:/org/apache/dubbo/config/spring/propertyconfigurer/consumer2/dubbo-consumer.xml")
- @PropertySource("classpath:/org/apache/dubbo/config/spring/propertyconfigurer/consumer2/app.properties")
static class ConsumerConfiguration {
@Bean
public DemoBeanFactoryPostProcessor bizBeanFactoryPostProcessor(HelloService service) {
diff --git a/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/propertyconfigurer/consumer3/PropertySourcesInJavaConfigTest.java b/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/propertyconfigurer/consumer3/PropertySourcesInJavaConfigTest.java
new file mode 100644
index 0000000..cd521119
--- /dev/null
+++ b/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/propertyconfigurer/consumer3/PropertySourcesInJavaConfigTest.java
@@ -0,0 +1,160 @@
+/*
+ * 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.propertyconfigurer.consumer3;
+
+import org.apache.dubbo.config.bootstrap.DubboBootstrap;
+import org.apache.dubbo.config.spring.ZooKeeperServer;
+import org.apache.dubbo.config.spring.api.HelloService;
+import org.apache.dubbo.config.spring.context.annotation.EnableDubbo;
+import org.apache.dubbo.config.spring.propertyconfigurer.consumer.DemoBeanFactoryPostProcessor;
+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.ComponentScan;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.ImportResource;
+import org.springframework.context.annotation.PropertySource;
+import org.springframework.context.support.ClassPathXmlApplicationContext;
+import org.springframework.context.support.PropertySourcesPlaceholderConfigurer;
+import org.springframework.core.io.ClassPathResource;
+
+public class PropertySourcesInJavaConfigTest {
+
+ private static final String SCAN_PACKAGE_NAME = "org.apache.dubbo.config.spring.propertyconfigurer.consumer3.notexist";
+ private static final String PACKAGE_PATH = "/org/apache/dubbo/config/spring/propertyconfigurer/consumer3";
+ private static final String PROVIDER_CONFIG_PATH = "org/apache/dubbo/config/spring/propertyconfigurer/provider/dubbo-provider.xml";
+
+ @BeforeAll
+ public static void setUp() {
+ ZooKeeperServer.start();
+ }
+
+ @BeforeEach
+ public void beforeTest() {
+ DubboBootstrap.reset();
+ }
+
+ @Test
+ public void testImportPropertySource() {
+
+ ClassPathXmlApplicationContext providerContext = new ClassPathXmlApplicationContext(PROVIDER_CONFIG_PATH);
+ try {
+ providerContext.start();
+
+ try {
+ Thread.sleep(1000);
+ } catch (InterruptedException e) {
+ }
+
+ // reset config
+ DubboBootstrap.reset(false);
+
+ // Resolve placeholder by import property sources
+ AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(ConsumerConfiguration.class, ImportPropertyConfiguration.class);
+ try {
+ // expect auto create PropertySourcesPlaceholderConfigurer bean
+ String[] beanNames = context.getBeanNamesForType(PropertySourcesPlaceholderConfigurer.class);
+ Assertions.assertEquals(1, beanNames.length);
+ Assertions.assertEquals(PropertySourcesPlaceholderConfigurer.class.getName(), beanNames[0]);
+
+ HelloService service = (HelloService) context.getBean("demoService");
+ String result = service.sayHello("world");
+ System.out.println("result: " + result);
+ Assertions.assertEquals("Hello world, response from provider: 127.0.0.1:0", result);
+ } finally {
+ context.close();
+ }
+
+ } finally {
+ providerContext.close();
+ }
+ }
+
+ @Test
+ public void testCustomPropertySourceBean() {
+
+ ClassPathXmlApplicationContext providerContext = new ClassPathXmlApplicationContext(PROVIDER_CONFIG_PATH);
+ try {
+ providerContext.start();
+
+ try {
+ Thread.sleep(1000);
+ } catch (InterruptedException e) {
+ }
+
+ // reset config
+ DubboBootstrap.reset(false);
+
+ // Resolve placeholder by custom PropertySourcesPlaceholderConfigurer bean
+ AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(ConsumerConfiguration.class, PropertyBeanConfiguration.class);
+ try {
+ // expect using custom PropertySourcesPlaceholderConfigurer bean
+ String[] beanNames = context.getBeanNamesForType(PropertySourcesPlaceholderConfigurer.class);
+ Assertions.assertEquals(1, beanNames.length);
+ Assertions.assertEquals("myPropertySourcesPlaceholderConfigurer", beanNames[0]);
+
+ HelloService service = (HelloService) context.getBean("demoService");
+ String result = service.sayHello("world");
+ System.out.println("result: " + result);
+ Assertions.assertEquals("Hello world, response from provider: 127.0.0.1:0", result);
+ } finally {
+ context.close();
+ }
+
+ } finally {
+ providerContext.close();
+ }
+ }
+
+ @Configuration
+ @EnableDubbo(scanBasePackages = SCAN_PACKAGE_NAME)
+ @ComponentScan(value = {SCAN_PACKAGE_NAME})
+ @ImportResource("classpath:" + PACKAGE_PATH + "/dubbo-consumer.xml")
+ static class ConsumerConfiguration {
+ @Bean
+ public DemoBeanFactoryPostProcessor bizBeanFactoryPostProcessor(HelloService service) {
+ return new DemoBeanFactoryPostProcessor(service);
+ }
+ }
+
+ @Configuration
+ @PropertySource("classpath:" + PACKAGE_PATH + "/app.properties")
+ static class ImportPropertyConfiguration {
+
+ }
+
+ @Configuration
+ static class PropertyBeanConfiguration {
+ @Bean
+ public MyPropertySourcesPlaceholderConfigurer myPropertySourcesPlaceholderConfigurer() {
+ MyPropertySourcesPlaceholderConfigurer placeholderConfigurer = new MyPropertySourcesPlaceholderConfigurer();
+ placeholderConfigurer.setLocation(new ClassPathResource(PACKAGE_PATH + "/app.properties"));
+ return placeholderConfigurer;
+ }
+ }
+
+ static class MyPropertySourcesPlaceholderConfigurer extends PropertySourcesPlaceholderConfigurer {
+ @Override
+ protected String convertProperty(String propertyName, String propertyValue) {
+ // .. do something ..
+ return propertyValue;
+ }
+ }
+}
diff --git a/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/propertyconfigurer/consumer3/app.properties b/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/propertyconfigurer/consumer3/app.properties
new file mode 100644
index 0000000..fcda447
--- /dev/null
+++ b/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/propertyconfigurer/consumer3/app.properties
@@ -0,0 +1,4 @@
+dubbo.registry.address=zookeeper://127.0.0.1:2181?registry-type=service
+biz.group=greeting
+biz.group2=group2
+dubbo.call-timeout=2000
diff --git a/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/propertyconfigurer/consumer3/dubbo-consumer.xml b/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/propertyconfigurer/consumer3/dubbo-consumer.xml
new file mode 100644
index 0000000..c5233e7
--- /dev/null
+++ b/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/propertyconfigurer/consumer3/dubbo-consumer.xml
@@ -0,0 +1,36 @@
+<?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" xmlns:context="http://www.springframework.org/schema/context"
+ xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.3.xsd
+ http://dubbo.apache.org/schema/dubbo http://dubbo.apache.org/schema/dubbo/dubbo.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
+
+ <dubbo:application name="demo-consumer">
+ </dubbo:application>
+
+ <!-- <dubbo:metadata-report address="zookeeper://127.0.0.1:2181"/>-->
+
+ <dubbo:registry address="${dubbo.registry.address}"/>
+
+ <!-- timeout="${dubbo.call-timeout}" -->
+ <dubbo:reference id="demoService" check="false" group="${biz.group}" timeout="${dubbo.call-timeout:foo-timeout}"
+ interface="org.apache.dubbo.config.spring.api.HelloService"/>
+
+
+</beans>
diff --git a/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/reference/ReferenceKeyTest.java b/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/reference/ReferenceKeyTest.java
index 521c561..02385c8 100644
--- a/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/reference/ReferenceKeyTest.java
+++ b/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/reference/ReferenceKeyTest.java
@@ -116,9 +116,10 @@ public class ReferenceKeyTest {
Map<String, ReferenceBean> referenceBeanMap = context.getBeansOfType(ReferenceBean.class);
Assertions.fail("Reference bean check failed");
} catch (BeansException e) {
- String s = e.toString();
- Assertions.assertTrue(s.contains("Already exists another reference bean with the same bean name and type but difference attributes"), getStackTrace(e));
- Assertions.assertTrue(s.contains("ConsumerConfiguration2.demoService"), getStackTrace(e));
+ String msg = getStackTrace(e);
+ Assertions.assertTrue(msg.contains("Found equivalent ReferenceConfig with unique service name [demo/org.apache.dubbo.config.spring.api.DemoService:1.2.3]"), msg);
+// Assertions.assertTrue(msg.contains("Already exists another reference bean with the same bean name and type but difference attributes"), msg);
+// Assertions.assertTrue(msg.contains("ConsumerConfiguration2.demoService"), msg);
}
}
@@ -143,7 +144,8 @@ public class ReferenceKeyTest {
Map<String, ReferenceBean> referenceBeanMap = context.getBeansOfType(ReferenceBean.class);
Assertions.fail("Reference bean check failed");
} catch (BeansException e) {
- Assertions.assertTrue(e.getMessage().contains("Duplicate spring bean name: demoService"), getStackTrace(e));
+ String msg = getStackTrace(e);
+ Assertions.assertTrue(msg.contains("Duplicate spring bean name: demoService"), msg);
} finally {
if (context != null) {
context.close();
@@ -171,9 +173,10 @@ public class ReferenceKeyTest {
Map<String, ReferenceBean> referenceBeanMap = context.getBeansOfType(ReferenceBean.class);
Assertions.fail("Reference bean check failed");
} catch (BeansException e) {
- String checkString = "Already exists another bean definition with the same bean name, but cannot rename the reference bean name";
- Assertions.assertTrue(e.getMessage().contains(checkString), getStackTrace(e));
- Assertions.assertTrue(e.getMessage().contains("ConsumerConfiguration6.demoService"), getStackTrace(e));
+ String checkString = "Already exists another bean definition with the same bean name [demoService], but cannot rename the reference bean name";
+ String msg = getStackTrace(e);
+ Assertions.assertTrue(msg.contains(checkString), msg);
+ Assertions.assertTrue(msg.contains("ConsumerConfiguration6.demoService"), msg);
}
}
diff --git a/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/reference/localcallam/LocalCallMultipleReferenceAnnotationsTest.java b/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/reference/localcallam/LocalCallMultipleReferenceAnnotationsTest.java
index 57d4abd..62cdb51 100644
--- a/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/reference/localcallam/LocalCallMultipleReferenceAnnotationsTest.java
+++ b/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/reference/localcallam/LocalCallMultipleReferenceAnnotationsTest.java
@@ -71,15 +71,14 @@ public class LocalCallMultipleReferenceAnnotationsTest {
Assertions.assertEquals("Hello world, response from provider: 127.0.0.1:0", demoResult);
Map<String, ReferenceBean> referenceBeanMap = applicationContext.getBeansOfType(ReferenceBean.class);
- Assertions.assertEquals(3, referenceBeanMap.size());
+ Assertions.assertEquals(2, referenceBeanMap.size());
Assertions.assertTrue(referenceBeanMap.containsKey("&helloService"));
Assertions.assertTrue(referenceBeanMap.containsKey("&demoHelloService"));
- Assertions.assertTrue(referenceBeanMap.containsKey("&helloService3"));
//helloService3 and demoHelloService share the same ReferenceConfig instance
- ReferenceBean helloService3ReferenceBean = referenceBeanMap.get("&helloService3");
- ReferenceBean demoHelloServiceReferenceBean = referenceBeanMap.get("&demoHelloService");
- Assertions.assertTrue(helloService3ReferenceBean.getReferenceConfig() == demoHelloServiceReferenceBean.getReferenceConfig());
+ ReferenceBean helloService3ReferenceBean = applicationContext.getBean("&helloService3", ReferenceBean.class);
+ ReferenceBean demoHelloServiceReferenceBean = applicationContext.getBean("&demoHelloService", ReferenceBean.class);
+ Assertions.assertSame(helloService3ReferenceBean, demoHelloServiceReferenceBean);
}
diff --git a/dubbo-spring-boot/dubbo-spring-boot-autoconfigure/src/test/java/org/apache/dubbo/spring/boot/autoconfigure/DubboRelaxedBinding2AutoConfigurationTest.java b/dubbo-spring-boot/dubbo-spring-boot-autoconfigure/src/test/java/org/apache/dubbo/spring/boot/autoconfigure/DubboRelaxedBinding2AutoConfigurationTest.java
index b41cab1..6bc036e 100644
--- a/dubbo-spring-boot/dubbo-spring-boot-autoconfigure/src/test/java/org/apache/dubbo/spring/boot/autoconfigure/DubboRelaxedBinding2AutoConfigurationTest.java
+++ b/dubbo-spring-boot/dubbo-spring-boot-autoconfigure/src/test/java/org/apache/dubbo/spring/boot/autoconfigure/DubboRelaxedBinding2AutoConfigurationTest.java
@@ -20,6 +20,7 @@ import org.apache.dubbo.config.spring.beans.factory.annotation.ReferenceAnnotati
import org.apache.dubbo.config.spring.beans.factory.annotation.ServiceAnnotationPostProcessor;
import com.alibaba.spring.context.config.ConfigurationBeanBinder;
+import org.apache.dubbo.config.spring.util.DubboBeanUtils;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.ObjectProvider;
@@ -27,6 +28,7 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.PropertySource;
import org.springframework.core.env.Environment;
import org.springframework.test.context.junit4.SpringRunner;
@@ -64,23 +66,25 @@ public class DubboRelaxedBinding2AutoConfigurationTest {
private ObjectProvider<ServiceAnnotationPostProcessor> serviceAnnotationPostProcessor;
@Autowired
- private ObjectProvider<ReferenceAnnotationBeanPostProcessor> referenceAnnotationBeanPostProcessor;
-
- @Autowired
private Environment environment;
@Autowired
private Map<String, Environment> environments;
+ @Autowired
+ private ApplicationContext applicationContext;
+
@Test
public void testBeans() {
+
assertTrue(ClassUtils.isAssignableValue(BinderDubboConfigBinder.class, dubboConfigBinder));
assertNotNull(serviceAnnotationPostProcessor);
assertNotNull(serviceAnnotationPostProcessor.getIfAvailable());
+
+ ReferenceAnnotationBeanPostProcessor referenceAnnotationBeanPostProcessor = DubboBeanUtils.getReferenceAnnotationBeanPostProcessor(applicationContext);
assertNotNull(referenceAnnotationBeanPostProcessor);
- assertNotNull(referenceAnnotationBeanPostProcessor.getIfAvailable());
assertNotNull(environment);
assertNotNull(environments);
diff --git a/dubbo-spring-boot/dubbo-spring-boot-compatible/actuator/src/main/java/org/apache/dubbo/spring/boot/actuate/endpoint/metadata/AbstractDubboMetadata.java b/dubbo-spring-boot/dubbo-spring-boot-compatible/actuator/src/main/java/org/apache/dubbo/spring/boot/actuate/endpoint/metadata/AbstractDubboMetadata.java
index 27ad5c9..4030f47 100644
--- a/dubbo-spring-boot/dubbo-spring-boot-compatible/actuator/src/main/java/org/apache/dubbo/spring/boot/actuate/endpoint/metadata/AbstractDubboMetadata.java
+++ b/dubbo-spring-boot/dubbo-spring-boot-compatible/actuator/src/main/java/org/apache/dubbo/spring/boot/actuate/endpoint/metadata/AbstractDubboMetadata.java
@@ -20,6 +20,7 @@ import org.apache.dubbo.config.ProtocolConfig;
import org.apache.dubbo.config.spring.ServiceBean;
import org.apache.dubbo.config.spring.beans.factory.annotation.ReferenceAnnotationBeanPostProcessor;
+import org.apache.dubbo.config.spring.util.DubboBeanUtils;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
@@ -38,7 +39,6 @@ import java.util.Date;
import java.util.LinkedHashMap;
import java.util.Map;
-import static org.apache.dubbo.config.spring.beans.factory.annotation.ReferenceAnnotationBeanPostProcessor.BEAN_NAME;
import static org.springframework.beans.factory.BeanFactoryUtils.beansOfTypeIncludingAncestors;
import static org.springframework.util.ClassUtils.isPrimitiveOrWrapper;
@@ -113,7 +113,7 @@ public abstract class AbstractDubboMetadata implements ApplicationContextAware,
}
protected ReferenceAnnotationBeanPostProcessor getReferenceAnnotationBeanPostProcessor() {
- return applicationContext.getBean(BEAN_NAME, ReferenceAnnotationBeanPostProcessor.class);
+ return DubboBeanUtils.getReferenceAnnotationBeanPostProcessor(applicationContext);
}
protected Map<String, ProtocolConfig> getProtocolConfigsBeanMap() {
diff --git a/dubbo-spring-boot/dubbo-spring-boot-compatible/autoconfigure/src/test/java/org/apache/dubbo/spring/boot/autoconfigure/CompatibleDubboAutoConfigurationTest.java b/dubbo-spring-boot/dubbo-spring-boot-compatible/autoconfigure/src/test/java/org/apache/dubbo/spring/boot/autoconfigure/CompatibleDubboAutoConfigurationTest.java
index 6713dee..169d2ba 100644
--- a/dubbo-spring-boot/dubbo-spring-boot-compatible/autoconfigure/src/test/java/org/apache/dubbo/spring/boot/autoconfigure/CompatibleDubboAutoConfigurationTest.java
+++ b/dubbo-spring-boot/dubbo-spring-boot-compatible/autoconfigure/src/test/java/org/apache/dubbo/spring/boot/autoconfigure/CompatibleDubboAutoConfigurationTest.java
@@ -19,6 +19,7 @@ package org.apache.dubbo.spring.boot.autoconfigure;
import org.apache.dubbo.config.spring.beans.factory.annotation.ReferenceAnnotationBeanPostProcessor;
import org.apache.dubbo.config.spring.beans.factory.annotation.ServiceAnnotationPostProcessor;
+import org.apache.dubbo.config.spring.util.DubboBeanUtils;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -26,6 +27,7 @@ import org.springframework.beans.factory.ObjectProvider;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.PropertySource;
import org.springframework.test.context.junit4.SpringRunner;
@@ -47,13 +49,14 @@ public class CompatibleDubboAutoConfigurationTest {
private ObjectProvider<ServiceAnnotationPostProcessor> serviceAnnotationPostProcessor;
@Autowired
- private ObjectProvider<ReferenceAnnotationBeanPostProcessor> referenceAnnotationBeanPostProcessor;
+ private ApplicationContext applicationContext;
@Test
public void testBeans() {
Assert.assertNotNull(serviceAnnotationPostProcessor);
Assert.assertNotNull(serviceAnnotationPostProcessor.getIfAvailable());
+
+ ReferenceAnnotationBeanPostProcessor referenceAnnotationBeanPostProcessor = DubboBeanUtils.getReferenceAnnotationBeanPostProcessor(applicationContext);
Assert.assertNotNull(referenceAnnotationBeanPostProcessor);
- Assert.assertNotNull(referenceAnnotationBeanPostProcessor.getIfAvailable());
}
}
diff --git a/dubbo-spring-boot/dubbo-spring-boot-compatible/autoconfigure/src/test/java/org/apache/dubbo/spring/boot/autoconfigure/CompatibleDubboAutoConfigurationTestWithoutProperties.java b/dubbo-spring-boot/dubbo-spring-boot-compatible/autoconfigure/src/test/java/org/apache/dubbo/spring/boot/autoconfigure/CompatibleDubboAutoConfigurationTestWithoutProperties.java
index 2feb074..bca8630 100644
--- a/dubbo-spring-boot/dubbo-spring-boot-compatible/autoconfigure/src/test/java/org/apache/dubbo/spring/boot/autoconfigure/CompatibleDubboAutoConfigurationTestWithoutProperties.java
+++ b/dubbo-spring-boot/dubbo-spring-boot-compatible/autoconfigure/src/test/java/org/apache/dubbo/spring/boot/autoconfigure/CompatibleDubboAutoConfigurationTestWithoutProperties.java
@@ -20,6 +20,7 @@ import org.apache.dubbo.config.bootstrap.DubboBootstrap;
import org.apache.dubbo.config.spring.beans.factory.annotation.ReferenceAnnotationBeanPostProcessor;
import org.apache.dubbo.config.spring.beans.factory.annotation.ServiceAnnotationPostProcessor;
+import org.apache.dubbo.config.spring.util.DubboBeanUtils;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
@@ -28,6 +29,7 @@ import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.context.ApplicationContext;
import org.springframework.test.context.junit4.SpringRunner;
/**
@@ -46,7 +48,7 @@ public class CompatibleDubboAutoConfigurationTestWithoutProperties {
private ServiceAnnotationPostProcessor serviceAnnotationPostProcessor;
@Autowired
- private ReferenceAnnotationBeanPostProcessor referenceAnnotationBeanPostProcessor;
+ private ApplicationContext applicationContext;
@Before
public void init() {
@@ -61,6 +63,8 @@ public class CompatibleDubboAutoConfigurationTestWithoutProperties {
@Test
public void testBeans() {
Assert.assertNull(serviceAnnotationPostProcessor);
+
+ ReferenceAnnotationBeanPostProcessor referenceAnnotationBeanPostProcessor = DubboBeanUtils.getReferenceAnnotationBeanPostProcessor(applicationContext);
Assert.assertNotNull(referenceAnnotationBeanPostProcessor);
}
}