You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@dubbo.apache.org by li...@apache.org on 2019/07/02 02:17:30 UTC
[dubbo] branch 2.7.3-release updated: DubboComponentScan cannot
backward support for alibaba @Service and @Reference. (#4415)
This is an automated email from the ASF dual-hosted git repository.
liujun pushed a commit to branch 2.7.3-release
in repository https://gitbox.apache.org/repos/asf/dubbo.git
The following commit(s) were added to refs/heads/2.7.3-release by this push:
new 60ca9f4 DubboComponentScan cannot backward support for alibaba @Service and @Reference. (#4415)
60ca9f4 is described below
commit 60ca9f4826ebb84ff41737c2ba2b60484eedc0f9
Author: Mercy Ma <me...@gmail.com>
AuthorDate: Tue Jul 2 10:17:12 2019 +0800
DubboComponentScan cannot backward support for alibaba @Service and @Reference. (#4415)
fixes #4330, #4409
---
.../org/apache/dubbo/common/utils/PojoUtils.java | 2 +-
.../apache/dubbo/common/utils/PojoUtilsTest.java | 19 +
.../spring/context/annotation/EnableDubbo.java | 12 +-
...atibleReferenceAnnotationBeanPostProcessor.java | 508 --------------------
.../annotation/CompatibleReferenceBeanBuilder.java | 167 -------
...mpatibleServiceAnnotationBeanPostProcessor.java | 525 ---------------------
.../annotation/CompatibleDubboComponentScan.java | 66 ---
.../CompatibleDubboComponentScanRegistrar.java | 110 -----
.../CompatibleAnnotationBeanDefinitionParser.java | 93 ----
.../AbstractAnnotationConfigBeanBuilder.java | 3 +
.../AnnotatedInterfaceConfigBeanBuilder.java | 215 +++++++++
.../AnnotationInjectedBeanPostProcessor.java | 128 ++---
.../AnnotationPropertyValuesAdapter.java | 39 +-
.../ReferenceAnnotationBeanPostProcessor.java | 32 +-
.../factory/annotation/ReferenceBeanBuilder.java | 84 ++--
.../ServiceAnnotationBeanPostProcessor.java | 6 +-
.../factory/annotation/ServiceBeanNameBuilder.java | 5 +-
.../util/AnnotatedBeanDefinitionRegistryUtils.java | 62 ++-
.../dubbo/config/spring/util/AnnotationUtils.java | 135 ++++--
.../dubbo/config/spring/util/BeanFactoryUtils.java | 6 +
.../merged/MergedReference.java} | 35 +-
.../merged/MergedService.java} | 33 +-
.../factory/annotation/MergedAnnotationTest.java | 76 +++
.../ReferenceAnnotationBeanPostProcessorTest.java | 2 +-
.../annotation/provider/DefaultHelloService.java | 4 +-
.../AnnotatedBeanDefinitionRegistryUtilsTest.java | 74 +++
26 files changed, 749 insertions(+), 1692 deletions(-)
diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/utils/PojoUtils.java b/dubbo-common/src/main/java/org/apache/dubbo/common/utils/PojoUtils.java
index 3bab261..52204ac 100644
--- a/dubbo-common/src/main/java/org/apache/dubbo/common/utils/PojoUtils.java
+++ b/dubbo-common/src/main/java/org/apache/dubbo/common/utils/PojoUtils.java
@@ -366,7 +366,7 @@ public class PojoUtils {
history.put(pojo, dest);
for (Object obj : src) {
Type keyType = getGenericClassByIndex(genericType, 0);
- Class<?> keyClazz = obj.getClass();
+ Class<?> keyClazz = obj == null ? null : obj.getClass();
if (keyType instanceof Class) {
keyClazz = (Class<?>) keyType;
}
diff --git a/dubbo-common/src/test/java/org/apache/dubbo/common/utils/PojoUtilsTest.java b/dubbo-common/src/test/java/org/apache/dubbo/common/utils/PojoUtilsTest.java
index 3595efb..f0ab173 100644
--- a/dubbo-common/src/test/java/org/apache/dubbo/common/utils/PojoUtilsTest.java
+++ b/dubbo-common/src/test/java/org/apache/dubbo/common/utils/PojoUtilsTest.java
@@ -37,6 +37,7 @@ import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
+import java.util.HashSet;
import java.util.Map;
import java.util.UUID;
@@ -682,6 +683,24 @@ public class PojoUtilsTest {
assertEquals(dateTimeStr, new SimpleDateFormat(dateFormat[0]).format(timestamp));
}
+ @Test
+ public void testRealizeCollectionWithNullElement() {
+ LinkedList<String> listStr = new LinkedList<>();
+ listStr.add("arrayValue");
+ listStr.add(null);
+ HashSet<String> setStr = new HashSet<>();
+ setStr.add("setValue");
+ setStr.add(null);
+
+ Object listResult = PojoUtils.realize(listStr, LinkedList.class);
+ assertEquals(LinkedList.class, listResult.getClass());
+ assertEquals(listResult, listStr);
+
+ Object setResult = PojoUtils.realize(setStr, HashSet.class);
+ assertEquals(HashSet.class, setResult.getClass());
+ assertEquals(setResult, setStr);
+ }
+
public enum Day {
SUNDAY, MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY
}
diff --git a/dubbo-compatible/src/main/java/com/alibaba/dubbo/config/spring/context/annotation/EnableDubbo.java b/dubbo-compatible/src/main/java/com/alibaba/dubbo/config/spring/context/annotation/EnableDubbo.java
index 1310d1a..d5227ed 100644
--- a/dubbo-compatible/src/main/java/com/alibaba/dubbo/config/spring/context/annotation/EnableDubbo.java
+++ b/dubbo-compatible/src/main/java/com/alibaba/dubbo/config/spring/context/annotation/EnableDubbo.java
@@ -18,7 +18,7 @@
package com.alibaba.dubbo.config.spring.context.annotation;
import org.apache.dubbo.config.AbstractConfig;
-import org.apache.dubbo.config.spring.context.annotation.CompatibleDubboComponentScan;
+import org.apache.dubbo.config.spring.context.annotation.DubboComponentScan;
import org.apache.dubbo.config.spring.context.annotation.EnableDubboConfig;
import org.springframework.core.annotation.AliasFor;
@@ -36,7 +36,7 @@ import java.lang.annotation.Target;
@Inherited
@Documented
@EnableDubboConfig
-@CompatibleDubboComponentScan
+@DubboComponentScan
public @interface EnableDubbo {
/**
@@ -46,9 +46,9 @@ public @interface EnableDubbo {
* package names.
*
* @return the base packages to scan
- * @see CompatibleDubboComponentScan#basePackages()
+ * @see DubboComponentScan#basePackages()
*/
- @AliasFor(annotation = CompatibleDubboComponentScan.class, attribute = "basePackages")
+ @AliasFor(annotation = DubboComponentScan.class, attribute = "basePackages")
String[] scanBasePackages() default {};
/**
@@ -57,9 +57,9 @@ public @interface EnableDubbo {
* scanned.
*
* @return classes from the base packages to scan
- * @see CompatibleDubboComponentScan#basePackageClasses
+ * @see DubboComponentScan#basePackageClasses
*/
- @AliasFor(annotation = CompatibleDubboComponentScan.class, attribute = "basePackageClasses")
+ @AliasFor(annotation = DubboComponentScan.class, attribute = "basePackageClasses")
Class<?>[] scanBasePackageClasses() default {};
diff --git a/dubbo-compatible/src/main/java/org/apache/dubbo/config/spring/beans/factory/annotation/CompatibleReferenceAnnotationBeanPostProcessor.java b/dubbo-compatible/src/main/java/org/apache/dubbo/config/spring/beans/factory/annotation/CompatibleReferenceAnnotationBeanPostProcessor.java
deleted file mode 100644
index d6826a5..0000000
--- a/dubbo-compatible/src/main/java/org/apache/dubbo/config/spring/beans/factory/annotation/CompatibleReferenceAnnotationBeanPostProcessor.java
+++ /dev/null
@@ -1,508 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.dubbo.config.spring.beans.factory.annotation;
-
-import org.apache.dubbo.config.spring.ReferenceBean;
-
-import com.alibaba.dubbo.config.annotation.Reference;
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.springframework.beans.BeanUtils;
-import org.springframework.beans.BeansException;
-import org.springframework.beans.PropertyValues;
-import org.springframework.beans.factory.BeanClassLoaderAware;
-import org.springframework.beans.factory.BeanCreationException;
-import org.springframework.beans.factory.DisposableBean;
-import org.springframework.beans.factory.annotation.InjectionMetadata;
-import org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessorAdapter;
-import org.springframework.beans.factory.support.MergedBeanDefinitionPostProcessor;
-import org.springframework.beans.factory.support.RootBeanDefinition;
-import org.springframework.context.ApplicationContext;
-import org.springframework.context.ApplicationContextAware;
-import org.springframework.core.PriorityOrdered;
-import org.springframework.core.env.Environment;
-import org.springframework.util.ClassUtils;
-import org.springframework.util.ReflectionUtils;
-import org.springframework.util.StringUtils;
-
-import java.beans.PropertyDescriptor;
-import java.lang.reflect.Field;
-import java.lang.reflect.Method;
-import java.lang.reflect.Modifier;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.LinkedHashMap;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Map;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.ConcurrentMap;
-
-import static org.springframework.core.BridgeMethodResolver.findBridgedMethod;
-import static org.springframework.core.BridgeMethodResolver.isVisibilityBridgeMethodPair;
-import static org.springframework.core.annotation.AnnotationUtils.findAnnotation;
-import static org.springframework.core.annotation.AnnotationUtils.getAnnotation;
-
-/**
- * {@link org.springframework.beans.factory.config.BeanPostProcessor} implementation
- * that Consumer service {@link Reference} annotated fields
- *
- * @since 2.5.7 deprecated since 2.7.0
- */
-@Deprecated
-public class CompatibleReferenceAnnotationBeanPostProcessor extends InstantiationAwareBeanPostProcessorAdapter
- implements MergedBeanDefinitionPostProcessor, PriorityOrdered, ApplicationContextAware, BeanClassLoaderAware,
- DisposableBean {
-
- /**
- * The bean name of {@link CompatibleReferenceAnnotationBeanPostProcessor}
- */
- public static final String BEAN_NAME = "compatibleReferenceAnnotationBeanPostProcessor";
-
- private final Log logger = LogFactory.getLog(getClass());
-
- private ApplicationContext applicationContext;
-
- private ClassLoader classLoader;
-
- private final ConcurrentMap<String, ReferenceInjectionMetadata> injectionMetadataCache =
- new ConcurrentHashMap<String, ReferenceInjectionMetadata>(256);
-
- private final ConcurrentMap<String, ReferenceBean<?>> referenceBeansCache =
- new ConcurrentHashMap<String, ReferenceBean<?>>();
-
- @Override
- public PropertyValues postProcessPropertyValues(
- PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeanCreationException {
-
- InjectionMetadata metadata = findReferenceMetadata(beanName, bean.getClass(), pvs);
- try {
- metadata.inject(bean, beanName, pvs);
- } catch (BeanCreationException ex) {
- throw ex;
- } catch (Throwable ex) {
- throw new BeanCreationException(beanName, "Injection of @Reference dependencies failed", ex);
- }
- return pvs;
- }
-
-
- /**
- * Finds {@link InjectionMetadata.InjectedElement} Metadata from annotated {@link Reference @Reference} fields
- *
- * @param beanClass The {@link Class} of Bean
- * @return non-null {@link List}
- */
- private List<ReferenceFieldElement> findFieldReferenceMetadata(final Class<?> beanClass) {
-
- final List<ReferenceFieldElement> elements = new LinkedList<ReferenceFieldElement>();
-
- ReflectionUtils.doWithFields(beanClass, new ReflectionUtils.FieldCallback() {
- @Override
- public void doWith(Field field) throws IllegalArgumentException, IllegalAccessException {
-
- Reference reference = getAnnotation(field, Reference.class);
-
- if (reference != null) {
-
- if (Modifier.isStatic(field.getModifiers())) {
- if (logger.isWarnEnabled()) {
- logger.warn("@Reference annotation is not supported on static fields: " + field);
- }
- return;
- }
-
- elements.add(new ReferenceFieldElement(field, reference));
- }
-
- }
- });
-
- return elements;
-
- }
-
- /**
- * Finds {@link InjectionMetadata.InjectedElement} Metadata from annotated {@link Reference @Reference} methods
- *
- * @param beanClass The {@link Class} of Bean
- * @return non-null {@link List}
- */
- private List<ReferenceMethodElement> findMethodReferenceMetadata(final Class<?> beanClass) {
-
- final List<ReferenceMethodElement> elements = new LinkedList<ReferenceMethodElement>();
-
- ReflectionUtils.doWithMethods(beanClass, new ReflectionUtils.MethodCallback() {
- @Override
- public void doWith(Method method) throws IllegalArgumentException, IllegalAccessException {
-
- Method bridgedMethod = findBridgedMethod(method);
-
- if (!isVisibilityBridgeMethodPair(method, bridgedMethod)) {
- return;
- }
-
- Reference reference = findAnnotation(bridgedMethod, Reference.class);
-
- if (reference != null && method.equals(ClassUtils.getMostSpecificMethod(method, beanClass))) {
- if (Modifier.isStatic(method.getModifiers())) {
- if (logger.isWarnEnabled()) {
- logger.warn("@Reference annotation is not supported on static methods: " + method);
- }
- return;
- }
- if (method.getParameterTypes().length == 0) {
- if (logger.isWarnEnabled()) {
- logger.warn("@Reference annotation should only be used on methods with parameters: " +
- method);
- }
- }
- PropertyDescriptor pd = BeanUtils.findPropertyForMethod(bridgedMethod, beanClass);
- elements.add(new ReferenceMethodElement(method, pd, reference));
- }
- }
- });
-
- return elements;
-
- }
-
-
- /**
- * @param beanClass
- * @return
- */
- private ReferenceInjectionMetadata buildReferenceMetadata(final Class<?> beanClass) {
- Collection<ReferenceFieldElement> fieldElements = findFieldReferenceMetadata(beanClass);
- Collection<ReferenceMethodElement> methodElements = findMethodReferenceMetadata(beanClass);
- return new ReferenceInjectionMetadata(beanClass, fieldElements, methodElements);
-
- }
-
- private InjectionMetadata findReferenceMetadata(String beanName, Class<?> clazz, PropertyValues pvs) {
- // Fall back to class name as cache key, for backwards compatibility with custom callers.
- String cacheKey = (StringUtils.hasLength(beanName) ? beanName : clazz.getName());
- // Quick check on the concurrent map first, with minimal locking.
- ReferenceInjectionMetadata metadata = this.injectionMetadataCache.get(cacheKey);
- if (InjectionMetadata.needsRefresh(metadata, clazz)) {
- synchronized (this.injectionMetadataCache) {
- metadata = this.injectionMetadataCache.get(cacheKey);
- if (InjectionMetadata.needsRefresh(metadata, clazz)) {
- if (metadata != null) {
- metadata.clear(pvs);
- }
- try {
- metadata = buildReferenceMetadata(clazz);
- this.injectionMetadataCache.put(cacheKey, metadata);
- } catch (NoClassDefFoundError err) {
- throw new IllegalStateException("Failed to introspect bean class [" + clazz.getName() +
- "] for reference metadata: could not find class that it depends on", err);
- }
- }
- }
- }
- return metadata;
- }
-
- @Override
- public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
- this.applicationContext = applicationContext;
- }
-
- @Override
- public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {
- if (beanType != null) {
- InjectionMetadata metadata = findReferenceMetadata(beanName, beanType, null);
- metadata.checkConfigMembers(beanDefinition);
- }
- }
-
- @Override
- public int getOrder() {
- return LOWEST_PRECEDENCE;
- }
-
- @Override
- public void destroy() throws Exception {
-
- for (ReferenceBean referenceBean : referenceBeansCache.values()) {
- if (logger.isInfoEnabled()) {
- logger.info(referenceBean + " was destroying!");
- }
- referenceBean.destroy();
- }
-
- injectionMetadataCache.clear();
- referenceBeansCache.clear();
-
- if (logger.isInfoEnabled()) {
- logger.info(getClass() + " was destroying!");
- }
-
- }
-
- @Override
- public void setBeanClassLoader(ClassLoader classLoader) {
- this.classLoader = classLoader;
- }
-
-
- /**
- * Gets all beans of {@link ReferenceBean}
- *
- * @return non-null {@link Collection}
- * @since 2.5.9
- */
- public Collection<ReferenceBean<?>> getReferenceBeans() {
- return this.referenceBeansCache.values();
- }
-
-
- /**
- * {@link Reference} {@link InjectionMetadata} implementation
- *
- * @since 2.5.11
- */
- private static class ReferenceInjectionMetadata extends InjectionMetadata {
-
- private final Collection<ReferenceFieldElement> fieldElements;
-
- private final Collection<ReferenceMethodElement> methodElements;
-
-
- public ReferenceInjectionMetadata(Class<?> targetClass, Collection<ReferenceFieldElement> fieldElements,
- Collection<ReferenceMethodElement> methodElements) {
- super(targetClass, combine(fieldElements, methodElements));
- this.fieldElements = fieldElements;
- this.methodElements = methodElements;
- }
-
- private static <T> Collection<T> combine(Collection<? extends T>... elements) {
- List<T> allElements = new ArrayList<T>();
- for (Collection<? extends T> e : elements) {
- allElements.addAll(e);
- }
- return allElements;
- }
-
- public Collection<ReferenceFieldElement> getFieldElements() {
- return fieldElements;
- }
-
- public Collection<ReferenceMethodElement> getMethodElements() {
- return methodElements;
- }
- }
-
- /**
- * {@link Reference} {@link Method} {@link InjectionMetadata.InjectedElement}
- */
- private class ReferenceMethodElement extends InjectionMetadata.InjectedElement {
-
- private final Method method;
-
- private final Reference reference;
-
- private volatile ReferenceBean<?> referenceBean;
-
- protected ReferenceMethodElement(Method method, PropertyDescriptor pd, Reference reference) {
- super(method, pd);
- this.method = method;
- this.reference = reference;
- }
-
- @Override
- protected void inject(Object bean, String beanName, PropertyValues pvs) throws Throwable {
-
- Class<?> referenceClass = pd.getPropertyType();
-
- referenceBean = buildReferenceBean(reference, referenceClass);
-
- ReflectionUtils.makeAccessible(method);
-
- method.invoke(bean, referenceBean.getObject());
-
- }
-
- }
-
- /**
- * {@link Reference} {@link Field} {@link InjectionMetadata.InjectedElement}
- */
- private class ReferenceFieldElement extends InjectionMetadata.InjectedElement {
-
- private final Field field;
-
- private final Reference reference;
-
- private volatile ReferenceBean<?> referenceBean;
-
- protected ReferenceFieldElement(Field field, Reference reference) {
- super(field, null);
- this.field = field;
- this.reference = reference;
- }
-
- @Override
- protected void inject(Object bean, String beanName, PropertyValues pvs) throws Throwable {
-
- Class<?> referenceClass = field.getType();
-
- referenceBean = buildReferenceBean(reference, referenceClass);
-
- ReflectionUtils.makeAccessible(field);
-
- field.set(bean, referenceBean.getObject());
-
- }
-
- }
-
- private ReferenceBean<?> buildReferenceBean(Reference reference, Class<?> referenceClass) throws Exception {
-
- String referenceBeanCacheKey = generateReferenceBeanCacheKey(reference, referenceClass);
-
- ReferenceBean<?> referenceBean = referenceBeansCache.get(referenceBeanCacheKey);
-
- if (referenceBean == null) {
-
- CompatibleReferenceBeanBuilder beanBuilder = CompatibleReferenceBeanBuilder
- .create(reference, classLoader, applicationContext)
- .interfaceClass(referenceClass);
-
- referenceBean = beanBuilder.build();
-
- referenceBeansCache.putIfAbsent(referenceBeanCacheKey, referenceBean);
-
- }
-
- return referenceBean;
-
- }
-
-
- /**
- * Generate a cache key of {@link ReferenceBean}
- *
- * @param reference {@link Reference}
- * @param beanClass {@link Class}
- * @return
- */
- private String generateReferenceBeanCacheKey(Reference reference, Class<?> beanClass) {
-
- String interfaceName = resolveInterfaceName(reference, beanClass);
-
- String key = reference.url() + "/" + interfaceName +
- "/" + reference.version() +
- "/" + reference.group();
-
- Environment environment = applicationContext.getEnvironment();
-
- key = environment.resolvePlaceholders(key);
-
- return key;
-
- }
-
- private static String resolveInterfaceName(Reference reference, Class<?> beanClass)
- throws IllegalStateException {
-
- String interfaceName;
- if (!"".equals(reference.interfaceName())) {
- interfaceName = reference.interfaceName();
- } else if (!void.class.equals(reference.interfaceClass())) {
- interfaceName = reference.interfaceClass().getName();
- } else if (beanClass.isInterface()) {
- interfaceName = beanClass.getName();
- } else {
- throw new IllegalStateException(
- "The @Reference undefined interfaceClass or interfaceName, and the property type "
- + beanClass.getName() + " is not a interface.");
- }
-
- return interfaceName;
-
- }
-
-
- /**
- * Get {@link ReferenceBean} {@link Map} in injected field.
- *
- * @return non-null {@link Map}
- * @since 2.5.11
- */
- public Map<InjectionMetadata.InjectedElement, ReferenceBean<?>> getInjectedFieldReferenceBeanMap() {
-
- Map<InjectionMetadata.InjectedElement, ReferenceBean<?>> injectedElementReferenceBeanMap =
- new LinkedHashMap<InjectionMetadata.InjectedElement, ReferenceBean<?>>();
-
- for (ReferenceInjectionMetadata metadata : injectionMetadataCache.values()) {
-
- Collection<ReferenceFieldElement> fieldElements = metadata.getFieldElements();
-
- for (ReferenceFieldElement fieldElement : fieldElements) {
-
- injectedElementReferenceBeanMap.put(fieldElement, fieldElement.referenceBean);
-
- }
-
- }
-
- return injectedElementReferenceBeanMap;
-
- }
-
- /**
- * Get {@link ReferenceBean} {@link Map} in injected method.
- *
- * @return non-null {@link Map}
- * @since 2.5.11
- */
- public Map<InjectionMetadata.InjectedElement, ReferenceBean<?>> getInjectedMethodReferenceBeanMap() {
-
- Map<InjectionMetadata.InjectedElement, ReferenceBean<?>> injectedElementReferenceBeanMap =
- new LinkedHashMap<InjectionMetadata.InjectedElement, ReferenceBean<?>>();
-
- for (ReferenceInjectionMetadata metadata : injectionMetadataCache.values()) {
-
- Collection<ReferenceMethodElement> methodElements = metadata.getMethodElements();
-
- for (ReferenceMethodElement methodElement : methodElements) {
-
- injectedElementReferenceBeanMap.put(methodElement, methodElement.referenceBean);
-
- }
-
- }
-
- return injectedElementReferenceBeanMap;
-
- }
-
- private <T> T getFieldValue(Object object, String fieldName, Class<T> fieldType) {
-
- Field field = ReflectionUtils.findField(object.getClass(), fieldName, fieldType);
-
- ReflectionUtils.makeAccessible(field);
-
- return (T) ReflectionUtils.getField(field, object);
-
- }
-
-
-}
diff --git a/dubbo-compatible/src/main/java/org/apache/dubbo/config/spring/beans/factory/annotation/CompatibleReferenceBeanBuilder.java b/dubbo-compatible/src/main/java/org/apache/dubbo/config/spring/beans/factory/annotation/CompatibleReferenceBeanBuilder.java
deleted file mode 100644
index 16013b3..0000000
--- a/dubbo-compatible/src/main/java/org/apache/dubbo/config/spring/beans/factory/annotation/CompatibleReferenceBeanBuilder.java
+++ /dev/null
@@ -1,167 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.dubbo.config.spring.beans.factory.annotation;
-
-import com.alibaba.dubbo.config.annotation.Reference;
-import org.apache.dubbo.common.utils.CollectionUtils;
-import org.apache.dubbo.config.ConsumerConfig;
-import org.apache.dubbo.config.spring.ReferenceBean;
-import org.springframework.beans.propertyeditors.StringTrimmerEditor;
-import org.springframework.context.ApplicationContext;
-import org.springframework.util.Assert;
-import org.springframework.util.ClassUtils;
-import org.springframework.util.StringUtils;
-import org.springframework.validation.DataBinder;
-
-import java.beans.PropertyEditorSupport;
-import java.util.Map;
-
-import static org.apache.dubbo.config.spring.util.BeanFactoryUtils.getOptionalBean;
-import static org.apache.dubbo.config.spring.util.ObjectUtils.of;
-import static org.springframework.util.StringUtils.commaDelimitedListToStringArray;
-
-/**
- * {@link ReferenceBean} Builder
- *
- * @since 2.5.7 deprecated since 2.7.0
- */
-@Deprecated
-class CompatibleReferenceBeanBuilder extends AbstractAnnotationConfigBeanBuilder<Reference, ReferenceBean> {
-
-
- // Ignore those fields
- static final String[] IGNORE_FIELD_NAMES = of("application", "module", "consumer", "monitor", "registry");
-
- private CompatibleReferenceBeanBuilder(Reference annotation, ClassLoader classLoader, ApplicationContext applicationContext) {
- super(annotation, classLoader, applicationContext);
- }
-
- private void configureInterface(Reference reference, ReferenceBean referenceBean) {
-
- Class<?> interfaceClass = reference.interfaceClass();
-
- if (void.class.equals(interfaceClass)) {
-
- interfaceClass = null;
-
- String interfaceClassName = reference.interfaceName();
-
- if (StringUtils.hasText(interfaceClassName)) {
- if (ClassUtils.isPresent(interfaceClassName, classLoader)) {
- interfaceClass = ClassUtils.resolveClassName(interfaceClassName, classLoader);
- }
- }
-
- }
-
- if (interfaceClass == null) {
- interfaceClass = this.interfaceClass;
- }
-
- Assert.isTrue(interfaceClass.isInterface(),
- "The class of field or method that was annotated @Reference is not an interface!");
-
- referenceBean.setInterface(interfaceClass);
-
- }
-
-
- private void configureConsumerConfig(Reference reference, ReferenceBean<?> referenceBean) {
-
- String consumerBeanName = reference.consumer();
-
- ConsumerConfig consumerConfig = getOptionalBean(applicationContext, consumerBeanName, ConsumerConfig.class);
-
- referenceBean.setConsumer(consumerConfig);
-
- }
-
- @Override
- protected ReferenceBean doBuild() {
- return new ReferenceBean<Object>();
- }
-
- @Override
- protected void preConfigureBean(Reference reference, ReferenceBean referenceBean) {
- Assert.notNull(interfaceClass, "The interface class must set first!");
- DataBinder dataBinder = new DataBinder(referenceBean);
- // Register CustomEditors for special fields
- dataBinder.registerCustomEditor(String.class, "filter", new StringTrimmerEditor(true));
- dataBinder.registerCustomEditor(String.class, "listener", new StringTrimmerEditor(true));
- dataBinder.registerCustomEditor(Map.class, "parameters", new PropertyEditorSupport() {
- @Override
- public void setAsText(String text) throws java.lang.IllegalArgumentException {
- // Trim all whitespace
- String content = StringUtils.trimAllWhitespace(text);
- if (!StringUtils.hasText(content)) { // No content , ignore directly
- return;
- }
- // replace "=" to ","
- content = StringUtils.replace(content, "=", ",");
- // replace ":" to ","
- content = StringUtils.replace(content, ":", ",");
- // String[] to Map
- Map<String, String> parameters = CollectionUtils.toStringMap(commaDelimitedListToStringArray(content));
- setValue(parameters);
- }
- });
-
- // Bind annotation attributes
- dataBinder.bind(new AnnotationPropertyValuesAdapter(reference, applicationContext.getEnvironment(), IGNORE_FIELD_NAMES));
-
- }
-
-
- @Override
- protected String resolveModuleConfigBeanName(Reference annotation) {
- return annotation.module();
- }
-
- @Override
- protected String resolveApplicationConfigBeanName(Reference annotation) {
- return annotation.application();
- }
-
- @Override
- protected String[] resolveRegistryConfigBeanNames(Reference annotation) {
- return annotation.registry();
- }
-
- @Override
- protected String resolveMonitorConfigBeanName(Reference annotation) {
- return annotation.monitor();
- }
-
- @Override
- protected void postConfigureBean(Reference annotation, ReferenceBean bean) throws Exception {
-
- bean.setApplicationContext(applicationContext);
-
- configureInterface(annotation, bean);
-
- configureConsumerConfig(annotation, bean);
-
- bean.afterPropertiesSet();
-
- }
-
- public static CompatibleReferenceBeanBuilder create(Reference annotation, ClassLoader classLoader,
- ApplicationContext applicationContext) {
- return new CompatibleReferenceBeanBuilder(annotation, classLoader, applicationContext);
- }
-
-}
diff --git a/dubbo-compatible/src/main/java/org/apache/dubbo/config/spring/beans/factory/annotation/CompatibleServiceAnnotationBeanPostProcessor.java b/dubbo-compatible/src/main/java/org/apache/dubbo/config/spring/beans/factory/annotation/CompatibleServiceAnnotationBeanPostProcessor.java
deleted file mode 100644
index 3d0370c..0000000
--- a/dubbo-compatible/src/main/java/org/apache/dubbo/config/spring/beans/factory/annotation/CompatibleServiceAnnotationBeanPostProcessor.java
+++ /dev/null
@@ -1,525 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.dubbo.config.spring.beans.factory.annotation;
-
-import org.apache.dubbo.common.logger.Logger;
-import org.apache.dubbo.common.logger.LoggerFactory;
-import org.apache.dubbo.common.utils.ArrayUtils;
-import org.apache.dubbo.config.spring.ServiceBean;
-import org.apache.dubbo.config.spring.context.annotation.DubboClassPathBeanDefinitionScanner;
-
-import com.alibaba.dubbo.config.annotation.Service;
-import org.springframework.beans.BeansException;
-import org.springframework.beans.MutablePropertyValues;
-import org.springframework.beans.factory.BeanClassLoaderAware;
-import org.springframework.beans.factory.config.BeanDefinition;
-import org.springframework.beans.factory.config.BeanDefinitionHolder;
-import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
-import org.springframework.beans.factory.config.RuntimeBeanReference;
-import org.springframework.beans.factory.config.SingletonBeanRegistry;
-import org.springframework.beans.factory.support.AbstractBeanDefinition;
-import org.springframework.beans.factory.support.BeanDefinitionBuilder;
-import org.springframework.beans.factory.support.BeanDefinitionRegistry;
-import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor;
-import org.springframework.beans.factory.support.BeanNameGenerator;
-import org.springframework.beans.factory.support.ManagedList;
-import org.springframework.context.EnvironmentAware;
-import org.springframework.context.ResourceLoaderAware;
-import org.springframework.context.annotation.AnnotationBeanNameGenerator;
-import org.springframework.context.annotation.AnnotationConfigUtils;
-import org.springframework.context.annotation.ClassPathBeanDefinitionScanner;
-import org.springframework.context.annotation.ConfigurationClassPostProcessor;
-import org.springframework.core.env.Environment;
-import org.springframework.core.io.ResourceLoader;
-import org.springframework.core.type.filter.AnnotationTypeFilter;
-import org.springframework.util.Assert;
-import org.springframework.util.ClassUtils;
-import org.springframework.util.CollectionUtils;
-import org.springframework.util.ObjectUtils;
-import org.springframework.util.StringUtils;
-
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.LinkedHashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-import static org.apache.dubbo.config.spring.util.ObjectUtils.of;
-import static org.springframework.beans.factory.support.BeanDefinitionBuilder.rootBeanDefinition;
-import static org.springframework.context.annotation.AnnotationConfigUtils.CONFIGURATION_BEAN_NAME_GENERATOR;
-import static org.springframework.core.annotation.AnnotationUtils.findAnnotation;
-import static org.springframework.util.ClassUtils.resolveClassName;
-
-/**
- * {@link Service} Annotation
- * {@link BeanDefinitionRegistryPostProcessor Bean Definition Registry Post Processor}
- *
- * @since 2.5.8 deprecated since 2.7.0
- */
-@Deprecated
-public class CompatibleServiceAnnotationBeanPostProcessor implements BeanDefinitionRegistryPostProcessor, EnvironmentAware,
- ResourceLoaderAware, BeanClassLoaderAware {
-
- private static final String SEPARATOR = ":";
-
- private final Logger logger = LoggerFactory.getLogger(getClass());
-
- private final Set<String> packagesToScan;
-
- private Environment environment;
-
- private ResourceLoader resourceLoader;
-
- private ClassLoader classLoader;
-
- public CompatibleServiceAnnotationBeanPostProcessor(String... packagesToScan) {
- this(Arrays.asList(packagesToScan));
- }
-
- public CompatibleServiceAnnotationBeanPostProcessor(Collection<String> packagesToScan) {
- this(new LinkedHashSet<String>(packagesToScan));
- }
-
- public CompatibleServiceAnnotationBeanPostProcessor(Set<String> packagesToScan) {
- this.packagesToScan = packagesToScan;
- }
-
- @Override
- public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
-
- Set<String> resolvedPackagesToScan = resolvePackagesToScan(packagesToScan);
-
- if (!CollectionUtils.isEmpty(resolvedPackagesToScan)) {
- registerServiceBeans(resolvedPackagesToScan, registry);
- } else {
- if (logger.isWarnEnabled()) {
- logger.warn("packagesToScan is empty , ServiceBean registry will be ignored!");
- }
- }
-
- }
-
-
- /**
- * Registers Beans whose classes was annotated {@link Service}
- *
- * @param packagesToScan The base packages to scan
- * @param registry {@link BeanDefinitionRegistry}
- */
- private void registerServiceBeans(Set<String> packagesToScan, BeanDefinitionRegistry registry) {
-
- DubboClassPathBeanDefinitionScanner scanner =
- new DubboClassPathBeanDefinitionScanner(registry, environment, resourceLoader);
-
- BeanNameGenerator beanNameGenerator = resolveBeanNameGenerator(registry);
-
- scanner.setBeanNameGenerator(beanNameGenerator);
-
- scanner.addIncludeFilter(new AnnotationTypeFilter(Service.class));
-
- for (String packageToScan : packagesToScan) {
-
- // Registers @Service Bean first
- scanner.scan(packageToScan);
-
- // Finds all BeanDefinitionHolders of @Service whether @ComponentScan scans or not.
- Set<BeanDefinitionHolder> beanDefinitionHolders =
- findServiceBeanDefinitionHolders(scanner, packageToScan, registry, beanNameGenerator);
-
- if (!CollectionUtils.isEmpty(beanDefinitionHolders)) {
-
- for (BeanDefinitionHolder beanDefinitionHolder : beanDefinitionHolders) {
- registerServiceBean(beanDefinitionHolder, registry, scanner);
- }
-
- if (logger.isInfoEnabled()) {
- logger.info(beanDefinitionHolders.size() + " annotated Dubbo's @Service Components { " +
- beanDefinitionHolders +
- " } were scanned under package[" + packageToScan + "]");
- }
-
- } else {
-
- if (logger.isWarnEnabled()) {
- logger.warn("No Spring Bean annotating Dubbo's @Service was found under package["
- + packageToScan + "]");
- }
-
- }
-
- }
-
- }
-
- /**
- * It'd better to use BeanNameGenerator instance that should reference
- * {@link ConfigurationClassPostProcessor#componentScanBeanNameGenerator},
- * thus it maybe a potential problem on bean name generation.
- *
- * @param registry {@link BeanDefinitionRegistry}
- * @return {@link BeanNameGenerator} instance
- * @see SingletonBeanRegistry
- * @see AnnotationConfigUtils#CONFIGURATION_BEAN_NAME_GENERATOR
- * @see ConfigurationClassPostProcessor#processConfigBeanDefinitions
- * @since 2.5.8
- */
- private BeanNameGenerator resolveBeanNameGenerator(BeanDefinitionRegistry registry) {
-
- BeanNameGenerator beanNameGenerator = null;
-
- if (registry instanceof SingletonBeanRegistry) {
- SingletonBeanRegistry singletonBeanRegistry = SingletonBeanRegistry.class.cast(registry);
- beanNameGenerator = (BeanNameGenerator) singletonBeanRegistry.getSingleton(CONFIGURATION_BEAN_NAME_GENERATOR);
- }
-
- if (beanNameGenerator == null) {
-
- if (logger.isInfoEnabled()) {
-
- logger.info("BeanNameGenerator bean can't be found in BeanFactory with name ["
- + CONFIGURATION_BEAN_NAME_GENERATOR + "]");
- logger.info("BeanNameGenerator will be a instance of " +
- AnnotationBeanNameGenerator.class.getName() +
- " , it maybe a potential problem on bean name generation.");
- }
-
- beanNameGenerator = new AnnotationBeanNameGenerator();
-
- }
-
- return beanNameGenerator;
-
- }
-
- /**
- * Finds a {@link Set} of {@link BeanDefinitionHolder BeanDefinitionHolders} whose bean type annotated
- * {@link Service} Annotation.
- *
- * @param scanner {@link ClassPathBeanDefinitionScanner}
- * @param packageToScan package to scan
- * @param registry {@link BeanDefinitionRegistry}
- * @return non-null
- * @since 2.5.8
- */
- private Set<BeanDefinitionHolder> findServiceBeanDefinitionHolders(
- ClassPathBeanDefinitionScanner scanner, String packageToScan, BeanDefinitionRegistry registry,
- BeanNameGenerator beanNameGenerator) {
-
- Set<BeanDefinition> beanDefinitions = scanner.findCandidateComponents(packageToScan);
-
- Set<BeanDefinitionHolder> beanDefinitionHolders = new LinkedHashSet<BeanDefinitionHolder>(beanDefinitions.size());
-
- for (BeanDefinition beanDefinition : beanDefinitions) {
-
- String beanName = beanNameGenerator.generateBeanName(beanDefinition, registry);
- BeanDefinitionHolder beanDefinitionHolder = new BeanDefinitionHolder(beanDefinition, beanName);
- beanDefinitionHolders.add(beanDefinitionHolder);
-
- }
-
- return beanDefinitionHolders;
-
- }
-
- /**
- * Registers {@link ServiceBean} from new annotated {@link Service} {@link BeanDefinition}
- *
- * @param beanDefinitionHolder
- * @param registry
- * @param scanner
- * @see ServiceBean
- * @see BeanDefinition
- */
- private void registerServiceBean(BeanDefinitionHolder beanDefinitionHolder, BeanDefinitionRegistry registry,
- DubboClassPathBeanDefinitionScanner scanner) {
-
- Class<?> beanClass = resolveClass(beanDefinitionHolder);
-
- Service service = findAnnotation(beanClass, Service.class);
-
- Class<?> interfaceClass = resolveServiceInterfaceClass(beanClass, service);
-
- String annotatedServiceBeanName = beanDefinitionHolder.getBeanName();
-
- AbstractBeanDefinition serviceBeanDefinition =
- buildServiceBeanDefinition(service, interfaceClass, annotatedServiceBeanName);
-
- // ServiceBean Bean name
- String beanName = generateServiceBeanName(service, interfaceClass, annotatedServiceBeanName);
-
- if (scanner.checkCandidate(beanName, serviceBeanDefinition)) { // check duplicated candidate bean
- registry.registerBeanDefinition(beanName, serviceBeanDefinition);
-
- if (logger.isInfoEnabled()) {
- logger.warn("The BeanDefinition[" + serviceBeanDefinition +
- "] of ServiceBean has been registered with name : " + beanName);
- }
-
- } else {
-
- if (logger.isWarnEnabled()) {
- logger.warn("The Duplicated BeanDefinition[" + serviceBeanDefinition +
- "] of ServiceBean[ bean name : " + beanName +
- "] was be found , Did @CompatibleDubboComponentScan scan to same package in many times?");
- }
-
- }
-
- }
-
- /**
- * Generates the bean name of {@link ServiceBean}
- *
- * @param service
- * @param interfaceClass the class of interface annotated {@link Service}
- * @param annotatedServiceBeanName the bean name of annotated {@link Service}
- * @return ServiceBean@interfaceClassName#annotatedServiceBeanName
- * @since 2.5.9
- */
- private String generateServiceBeanName(Service service, Class<?> interfaceClass, String annotatedServiceBeanName) {
-
- StringBuilder beanNameBuilder = new StringBuilder(ServiceBean.class.getSimpleName());
-
- beanNameBuilder.append(SEPARATOR).append(annotatedServiceBeanName);
-
- String interfaceClassName = interfaceClass.getName();
-
- beanNameBuilder.append(SEPARATOR).append(interfaceClassName);
-
- String version = service.version();
-
- if (StringUtils.hasText(version)) {
- beanNameBuilder.append(SEPARATOR).append(version);
- }
-
- String group = service.group();
-
- if (StringUtils.hasText(group)) {
- beanNameBuilder.append(SEPARATOR).append(group);
- }
-
- return beanNameBuilder.toString();
-
- }
-
- private Class<?> resolveServiceInterfaceClass(Class<?> annotatedServiceBeanClass, Service service) {
-
- Class<?> interfaceClass = service.interfaceClass();
-
- if (void.class.equals(interfaceClass)) {
-
- interfaceClass = null;
-
- String interfaceClassName = service.interfaceName();
-
- if (StringUtils.hasText(interfaceClassName)) {
- if (ClassUtils.isPresent(interfaceClassName, classLoader)) {
- interfaceClass = resolveClassName(interfaceClassName, classLoader);
- }
- }
-
- }
-
- if (interfaceClass == null) {
-
- Class<?>[] allInterfaces = annotatedServiceBeanClass.getInterfaces();
-
- if (allInterfaces.length > 0) {
- interfaceClass = allInterfaces[0];
- }
-
- }
-
- Assert.notNull(interfaceClass,
- "@Service interfaceClass() or interfaceName() or interface class must be present!");
-
- Assert.isTrue(interfaceClass.isInterface(),
- "The type that was annotated @Service is not an interface!");
-
- return interfaceClass;
- }
-
- private Class<?> resolveClass(BeanDefinitionHolder beanDefinitionHolder) {
-
- BeanDefinition beanDefinition = beanDefinitionHolder.getBeanDefinition();
-
- return resolveClass(beanDefinition);
-
- }
-
- private Class<?> resolveClass(BeanDefinition beanDefinition) {
-
- String beanClassName = beanDefinition.getBeanClassName();
-
- return resolveClassName(beanClassName, classLoader);
-
- }
-
- private Set<String> resolvePackagesToScan(Set<String> packagesToScan) {
- Set<String> resolvedPackagesToScan = new LinkedHashSet<String>(packagesToScan.size());
- for (String packageToScan : packagesToScan) {
- if (StringUtils.hasText(packageToScan)) {
- String resolvedPackageToScan = environment.resolvePlaceholders(packageToScan.trim());
- resolvedPackagesToScan.add(resolvedPackageToScan);
- }
- }
- return resolvedPackagesToScan;
- }
-
- private AbstractBeanDefinition buildServiceBeanDefinition(Service service, Class<?> interfaceClass,
- String annotatedServiceBeanName) {
-
- BeanDefinitionBuilder builder = rootBeanDefinition(ServiceBean.class);
-
- AbstractBeanDefinition beanDefinition = builder.getBeanDefinition();
-
- MutablePropertyValues propertyValues = beanDefinition.getPropertyValues();
-
- String[] ignoreAttributeNames = of("provider", "monitor", "application", "module", "registry", "protocol",
- "interface", "parameters");
-
- propertyValues.addPropertyValues(new AnnotationPropertyValuesAdapter(service, environment, ignoreAttributeNames));
-
- // References "ref" property to annotated-@Service Bean
- addPropertyReference(builder, "ref", annotatedServiceBeanName);
- // Set interface
- builder.addPropertyValue("interface", interfaceClass.getName());
- // Convert parameters into map
- builder.addPropertyValue("parameters", convertParameters(service.parameters()));
-
- /**
- * Add {@link org.apache.dubbo.config.ProviderConfig} Bean reference
- */
- String providerConfigBeanName = service.provider();
- if (StringUtils.hasText(providerConfigBeanName)) {
- addPropertyReference(builder, "provider", providerConfigBeanName);
- }
-
- /**
- * Add {@link org.apache.dubbo.config.MonitorConfig} Bean reference
- */
- String monitorConfigBeanName = service.monitor();
- if (StringUtils.hasText(monitorConfigBeanName)) {
- addPropertyReference(builder, "monitor", monitorConfigBeanName);
- }
-
- /**
- * Add {@link org.apache.dubbo.config.ApplicationConfig} Bean reference
- */
- String applicationConfigBeanName = service.application();
- if (StringUtils.hasText(applicationConfigBeanName)) {
- addPropertyReference(builder, "application", applicationConfigBeanName);
- }
-
- /**
- * Add {@link org.apache.dubbo.config.ModuleConfig} Bean reference
- */
- String moduleConfigBeanName = service.module();
- if (StringUtils.hasText(moduleConfigBeanName)) {
- addPropertyReference(builder, "module", moduleConfigBeanName);
- }
-
-
- /**
- * Add {@link org.apache.dubbo.config.RegistryConfig} Bean reference
- */
- String[] registryConfigBeanNames = service.registry();
-
- List<RuntimeBeanReference> registryRuntimeBeanReferences = toRuntimeBeanReferences(registryConfigBeanNames);
-
- if (!registryRuntimeBeanReferences.isEmpty()) {
- builder.addPropertyValue("registries", registryRuntimeBeanReferences);
- }
-
- /**
- * Add {@link org.apache.dubbo.config.ProtocolConfig} Bean reference
- */
- String[] protocolConfigBeanNames = service.protocol();
-
- List<RuntimeBeanReference> protocolRuntimeBeanReferences = toRuntimeBeanReferences(protocolConfigBeanNames);
-
- if (!protocolRuntimeBeanReferences.isEmpty()) {
- builder.addPropertyValue("protocols", protocolRuntimeBeanReferences);
- }
-
- return builder.getBeanDefinition();
-
- }
-
-
- private ManagedList<RuntimeBeanReference> toRuntimeBeanReferences(String... beanNames) {
-
- ManagedList<RuntimeBeanReference> runtimeBeanReferences = new ManagedList<RuntimeBeanReference>();
-
- if (!ObjectUtils.isEmpty(beanNames)) {
-
- for (String beanName : beanNames) {
-
- String resolvedBeanName = environment.resolvePlaceholders(beanName);
-
- runtimeBeanReferences.add(new RuntimeBeanReference(resolvedBeanName));
- }
-
- }
-
- return runtimeBeanReferences;
-
- }
-
- private void addPropertyReference(BeanDefinitionBuilder builder, String propertyName, String beanName) {
- String resolvedBeanName = environment.resolvePlaceholders(beanName);
- builder.addPropertyReference(propertyName, resolvedBeanName);
- }
-
- private Map<String, String> convertParameters(String[] parameters) {
- if (ArrayUtils.isEmpty(parameters)) {
- return null;
- }
-
- if (parameters.length % 2 != 0) {
- throw new IllegalArgumentException("parameter attribute must be paired with key followed by value");
- }
-
- Map<String, String> map = new HashMap<>();
- for (int i = 0; i < parameters.length; i += 2) {
- map.put(parameters[i], parameters[i + 1]);
- }
- return map;
- }
-
- @Override
- public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
-
- }
-
- @Override
- public void setEnvironment(Environment environment) {
- this.environment = environment;
- }
-
- @Override
- public void setResourceLoader(ResourceLoader resourceLoader) {
- this.resourceLoader = resourceLoader;
- }
-
- @Override
- public void setBeanClassLoader(ClassLoader classLoader) {
- this.classLoader = classLoader;
- }
-}
diff --git a/dubbo-compatible/src/main/java/org/apache/dubbo/config/spring/context/annotation/CompatibleDubboComponentScan.java b/dubbo-compatible/src/main/java/org/apache/dubbo/config/spring/context/annotation/CompatibleDubboComponentScan.java
deleted file mode 100644
index 4b8e229..0000000
--- a/dubbo-compatible/src/main/java/org/apache/dubbo/config/spring/context/annotation/CompatibleDubboComponentScan.java
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.dubbo.config.spring.context.annotation;
-
-import org.springframework.context.annotation.Import;
-
-import java.lang.annotation.Documented;
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-
-/**
- * @since 2.5.7 deprecated since 2.7.0
- */
-@Deprecated
-@Target(ElementType.TYPE)
-@Retention(RetentionPolicy.RUNTIME)
-@Documented
-@Import(CompatibleDubboComponentScanRegistrar.class)
-public @interface CompatibleDubboComponentScan {
-
- /**
- * Alias for the {@link #basePackages()} attribute. Allows for more concise annotation
- * declarations e.g.: {@code @CompatibleDubboComponentScan("org.my.pkg")} instead of
- * {@code @CompatibleDubboComponentScan(basePackages="org.my.pkg")}.
- *
- * @return the base packages to scan
- */
- String[] value() default {};
-
- /**
- * Base packages to scan for annotated @Service classes. {@link #value()} is an
- * alias for (and mutually exclusive with) this attribute.
- * <p>
- * Use {@link #basePackageClasses()} for a type-safe alternative to String-based
- * package names.
- *
- * @return the base packages to scan
- */
- String[] basePackages() default {};
-
- /**
- * Type-safe alternative to {@link #basePackages()} for specifying the packages to
- * scan for annotated @Service classes. The package of each class specified will be
- * scanned.
- *
- * @return classes from the base packages to scan
- */
- Class<?>[] basePackageClasses() default {};
-
-}
diff --git a/dubbo-compatible/src/main/java/org/apache/dubbo/config/spring/context/annotation/CompatibleDubboComponentScanRegistrar.java b/dubbo-compatible/src/main/java/org/apache/dubbo/config/spring/context/annotation/CompatibleDubboComponentScanRegistrar.java
deleted file mode 100644
index 089bdda..0000000
--- a/dubbo-compatible/src/main/java/org/apache/dubbo/config/spring/context/annotation/CompatibleDubboComponentScanRegistrar.java
+++ /dev/null
@@ -1,110 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.dubbo.config.spring.context.annotation;
-
-import org.apache.dubbo.config.spring.beans.factory.annotation.CompatibleReferenceAnnotationBeanPostProcessor;
-import org.apache.dubbo.config.spring.beans.factory.annotation.CompatibleServiceAnnotationBeanPostProcessor;
-import org.apache.dubbo.config.spring.util.BeanRegistrar;
-
-import org.springframework.beans.factory.BeanFactory;
-import org.springframework.beans.factory.config.BeanDefinition;
-import org.springframework.beans.factory.support.AbstractBeanDefinition;
-import org.springframework.beans.factory.support.BeanDefinitionBuilder;
-import org.springframework.beans.factory.support.BeanDefinitionReaderUtils;
-import org.springframework.beans.factory.support.BeanDefinitionRegistry;
-import org.springframework.context.annotation.ImportBeanDefinitionRegistrar;
-import org.springframework.core.annotation.AnnotationAttributes;
-import org.springframework.core.type.AnnotationMetadata;
-import org.springframework.util.ClassUtils;
-
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.LinkedHashSet;
-import java.util.Set;
-
-import static org.springframework.beans.factory.support.BeanDefinitionBuilder.rootBeanDefinition;
-
-/**
- * Dubbo Bean Registrar
- * @see ImportBeanDefinitionRegistrar
- * @see CompatibleServiceAnnotationBeanPostProcessor
- * @see CompatibleReferenceAnnotationBeanPostProcessor
- * @since 2.5.7 deprecated since 2.7.0
- */
-@Deprecated
-public class CompatibleDubboComponentScanRegistrar implements ImportBeanDefinitionRegistrar {
-
- @Override
- public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
-
- Set<String> packagesToScan = getPackagesToScan(importingClassMetadata);
-
- registerServiceAnnotationBeanPostProcessor(packagesToScan, registry);
-
- registerReferenceAnnotationBeanPostProcessor(registry);
-
- }
-
- /**
- * Registers {@link CompatibleServiceAnnotationBeanPostProcessor}
- *
- * @param packagesToScan packages to scan without resolving placeholders
- * @param registry {@link BeanDefinitionRegistry}
- * @since 2.5.8 deprecated since 2.7.0
- */
- private void registerServiceAnnotationBeanPostProcessor(Set<String> packagesToScan, BeanDefinitionRegistry registry) {
-
- BeanDefinitionBuilder builder = rootBeanDefinition(CompatibleServiceAnnotationBeanPostProcessor.class);
- builder.addConstructorArgValue(packagesToScan);
- builder.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
- AbstractBeanDefinition beanDefinition = builder.getBeanDefinition();
- BeanDefinitionReaderUtils.registerWithGeneratedName(beanDefinition, registry);
-
- }
-
- /**
- * Registers {@link CompatibleReferenceAnnotationBeanPostProcessor} into {@link BeanFactory}
- *
- * @param registry {@link BeanDefinitionRegistry}
- */
- private void registerReferenceAnnotationBeanPostProcessor(BeanDefinitionRegistry registry) {
-
- // Register @Reference Annotation Bean Processor
- BeanRegistrar.registerInfrastructureBean(registry,
- CompatibleReferenceAnnotationBeanPostProcessor.BEAN_NAME, CompatibleReferenceAnnotationBeanPostProcessor.class);
-
- }
-
- private Set<String> getPackagesToScan(AnnotationMetadata metadata) {
- AnnotationAttributes attributes = AnnotationAttributes.fromMap(
- metadata.getAnnotationAttributes(CompatibleDubboComponentScan.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));
- packagesToScan.addAll(Arrays.asList(basePackages));
- for (Class<?> basePackageClass : basePackageClasses) {
- packagesToScan.add(ClassUtils.getPackageName(basePackageClass));
- }
- if (packagesToScan.isEmpty()) {
- return Collections.singleton(ClassUtils.getPackageName(metadata.getClassName()));
- }
- return packagesToScan;
- }
-
-}
diff --git a/dubbo-compatible/src/main/java/org/apache/dubbo/config/spring/schema/CompatibleAnnotationBeanDefinitionParser.java b/dubbo-compatible/src/main/java/org/apache/dubbo/config/spring/schema/CompatibleAnnotationBeanDefinitionParser.java
deleted file mode 100644
index 1172591..0000000
--- a/dubbo-compatible/src/main/java/org/apache/dubbo/config/spring/schema/CompatibleAnnotationBeanDefinitionParser.java
+++ /dev/null
@@ -1,93 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.dubbo.config.spring.schema;
-
-import org.apache.dubbo.config.spring.beans.factory.annotation.CompatibleReferenceAnnotationBeanPostProcessor;
-import org.apache.dubbo.config.spring.beans.factory.annotation.CompatibleServiceAnnotationBeanPostProcessor;
-import org.apache.dubbo.config.spring.util.BeanRegistrar;
-import org.springframework.beans.factory.BeanFactory;
-import org.springframework.beans.factory.config.BeanDefinition;
-import org.springframework.beans.factory.support.BeanDefinitionBuilder;
-import org.springframework.beans.factory.support.BeanDefinitionRegistry;
-import org.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser;
-import org.springframework.beans.factory.xml.BeanDefinitionParser;
-import org.springframework.beans.factory.xml.ParserContext;
-import org.w3c.dom.Element;
-
-import static org.springframework.util.StringUtils.commaDelimitedListToStringArray;
-import static org.springframework.util.StringUtils.trimArrayElements;
-
-/**
- * {@link BeanDefinitionParser}
- *
- * @see CompatibleServiceAnnotationBeanPostProcessor
- * @see CompatibleReferenceAnnotationBeanPostProcessor
- * @since 2.5.9 deprecated since 2.7.0
- */
-@Deprecated
-public class CompatibleAnnotationBeanDefinitionParser extends AbstractSingleBeanDefinitionParser {
-
- /**
- * parse
- * <prev>
- * <dubbo:annotation package="" />
- * </prev>
- *
- * @param element
- * @param parserContext
- * @param builder
- */
- @Override
- protected void doParse(Element element, ParserContext parserContext, BeanDefinitionBuilder builder) {
-
- String packageToScan = element.getAttribute("package");
-
- String[] packagesToScan = trimArrayElements(commaDelimitedListToStringArray(packageToScan));
-
- builder.addConstructorArgValue(packagesToScan);
-
- builder.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
-
- // Registers CompatibleReferenceAnnotationBeanPostProcessor
- registerReferenceAnnotationBeanPostProcessor(parserContext.getRegistry());
-
- }
-
- @Override
- protected boolean shouldGenerateIdAsFallback() {
- return true;
- }
-
- /**
- * Registers {@link CompatibleReferenceAnnotationBeanPostProcessor} into {@link BeanFactory}
- *
- * @param registry {@link BeanDefinitionRegistry}
- */
- private void registerReferenceAnnotationBeanPostProcessor(BeanDefinitionRegistry registry) {
-
- // Register @Reference Annotation Bean Processor
- BeanRegistrar.registerInfrastructureBean(registry,
- CompatibleReferenceAnnotationBeanPostProcessor.BEAN_NAME, CompatibleReferenceAnnotationBeanPostProcessor.class);
-
- }
-
- @Override
- protected Class<?> getBeanClass(Element element) {
- return CompatibleServiceAnnotationBeanPostProcessor.class;
- }
-
-}
diff --git a/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/beans/factory/annotation/AbstractAnnotationConfigBeanBuilder.java b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/beans/factory/annotation/AbstractAnnotationConfigBeanBuilder.java
index 7f7afd9..25da5d9 100644
--- a/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/beans/factory/annotation/AbstractAnnotationConfigBeanBuilder.java
+++ b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/beans/factory/annotation/AbstractAnnotationConfigBeanBuilder.java
@@ -35,8 +35,11 @@ import static org.apache.dubbo.config.spring.util.BeanFactoryUtils.getOptionalBe
/**
* Abstract Configurable {@link Annotation} Bean Builder
+ *
* @since 2.5.7
+ * @deprecated use {@link AnnotatedInterfaceConfigBeanBuilder}
*/
+@Deprecated
abstract class AbstractAnnotationConfigBeanBuilder<A extends Annotation, B extends AbstractInterfaceConfig> {
protected final Log logger = LogFactory.getLog(getClass());
diff --git a/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/beans/factory/annotation/AnnotatedInterfaceConfigBeanBuilder.java b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/beans/factory/annotation/AnnotatedInterfaceConfigBeanBuilder.java
new file mode 100644
index 0000000..32a37ba
--- /dev/null
+++ b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/beans/factory/annotation/AnnotatedInterfaceConfigBeanBuilder.java
@@ -0,0 +1,215 @@
+/*
+ * 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.beans.factory.annotation;
+
+import org.apache.dubbo.config.AbstractInterfaceConfig;
+import org.apache.dubbo.config.ApplicationConfig;
+import org.apache.dubbo.config.ModuleConfig;
+import org.apache.dubbo.config.MonitorConfig;
+import org.apache.dubbo.config.RegistryConfig;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.springframework.context.ApplicationContext;
+import org.springframework.core.annotation.AnnotationAttributes;
+import org.springframework.util.Assert;
+
+import java.lang.annotation.Annotation;
+import java.util.List;
+
+import static org.apache.dubbo.config.spring.util.BeanFactoryUtils.getBeans;
+import static org.apache.dubbo.config.spring.util.BeanFactoryUtils.getOptionalBean;
+
+/**
+ * An Abstract Builder to build {@link AbstractInterfaceConfig Interface Config} Bean that annotated
+ * some {@link Annotation annotation}.
+ *
+ * @see ReferenceBeanBuilder
+ * @see AbstractInterfaceConfig
+ * @see AnnotationAttributes
+ * @since 2.7.3
+ */
+public abstract class AnnotatedInterfaceConfigBeanBuilder<C extends AbstractInterfaceConfig> {
+
+ protected final Log logger = LogFactory.getLog(getClass());
+
+ protected final AnnotationAttributes attributes;
+
+ protected final ApplicationContext applicationContext;
+
+ protected final ClassLoader classLoader;
+
+ protected Object configBean;
+
+ protected Class<?> interfaceClass;
+
+ protected AnnotatedInterfaceConfigBeanBuilder(AnnotationAttributes attributes, ApplicationContext applicationContext) {
+ Assert.notNull(attributes, "The Annotation attributes must not be null!");
+ Assert.notNull(applicationContext, "The ApplicationContext must not be null!");
+ this.attributes = attributes;
+ this.applicationContext = applicationContext;
+ this.classLoader = applicationContext.getClassLoader() != null ?
+ applicationContext.getClassLoader() : Thread.currentThread().getContextClassLoader();
+ }
+
+ /**
+ * Build {@link C}
+ *
+ * @return non-null
+ * @throws Exception
+ */
+ public final C build() throws Exception {
+
+ checkDependencies();
+
+ C configBean = doBuild();
+
+ configureBean(configBean);
+
+ if (logger.isInfoEnabled()) {
+ logger.info("The configBean[type:" + configBean.getClass().getSimpleName() + "] has been built.");
+ }
+
+ return configBean;
+
+ }
+
+ private void checkDependencies() {
+
+ }
+
+ /**
+ * Builds {@link C Bean}
+ *
+ * @return {@link C Bean}
+ */
+ protected abstract C doBuild();
+
+
+ protected void configureBean(C configBean) throws Exception {
+
+ preConfigureBean(attributes, configBean);
+
+ configureRegistryConfigs(configBean);
+
+ configureMonitorConfig(configBean);
+
+ configureApplicationConfig(configBean);
+
+ configureModuleConfig(configBean);
+
+ postConfigureBean(attributes, configBean);
+
+ }
+
+ protected abstract void preConfigureBean(AnnotationAttributes attributes, C configBean) throws Exception;
+
+
+ private void configureRegistryConfigs(C configBean) {
+
+ String[] registryConfigBeanIds = resolveRegistryConfigBeanNames(attributes);
+
+ List<RegistryConfig> registryConfigs = getBeans(applicationContext, registryConfigBeanIds, RegistryConfig.class);
+
+ configBean.setRegistries(registryConfigs);
+
+ }
+
+ private void configureMonitorConfig(C configBean) {
+
+ String monitorBeanName = resolveMonitorConfigBeanName(attributes);
+
+ MonitorConfig monitorConfig = getOptionalBean(applicationContext, monitorBeanName, MonitorConfig.class);
+
+ configBean.setMonitor(monitorConfig);
+
+ }
+
+ private void configureApplicationConfig(C configBean) {
+
+ String applicationConfigBeanName = resolveApplicationConfigBeanName(attributes);
+
+ ApplicationConfig applicationConfig =
+ getOptionalBean(applicationContext, applicationConfigBeanName, ApplicationConfig.class);
+
+ configBean.setApplication(applicationConfig);
+
+ }
+
+ private void configureModuleConfig(C configBean) {
+
+ String moduleConfigBeanName = resolveModuleConfigBeanName(attributes);
+
+ ModuleConfig moduleConfig =
+ getOptionalBean(applicationContext, moduleConfigBeanName, ModuleConfig.class);
+
+ configBean.setModule(moduleConfig);
+
+ }
+
+ /**
+ * Resolves the configBean name of {@link ModuleConfig}
+ *
+ * @param attributes {@link AnnotationAttributes}
+ * @return
+ */
+ protected abstract String resolveModuleConfigBeanName(AnnotationAttributes attributes);
+
+ /**
+ * Resolves the configBean name of {@link ApplicationConfig}
+ *
+ * @param attributes {@link AnnotationAttributes}
+ * @return
+ */
+ protected abstract String resolveApplicationConfigBeanName(AnnotationAttributes attributes);
+
+
+ /**
+ * Resolves the configBean ids of {@link RegistryConfig}
+ *
+ * @param attributes {@link AnnotationAttributes}
+ * @return non-empty array
+ */
+ protected abstract String[] resolveRegistryConfigBeanNames(AnnotationAttributes attributes);
+
+ /**
+ * Resolves the configBean name of {@link MonitorConfig}
+ *
+ * @param attributes {@link AnnotationAttributes}
+ * @return
+ */
+ protected abstract String resolveMonitorConfigBeanName(AnnotationAttributes attributes);
+
+ /**
+ * Configures Bean
+ *
+ * @param attributes
+ * @param configBean
+ */
+ protected abstract void postConfigureBean(AnnotationAttributes attributes, C configBean) throws Exception;
+
+
+ public <T extends AnnotatedInterfaceConfigBeanBuilder<C>> T configBean(Object configBean) {
+ this.configBean = configBean;
+ return (T) this;
+ }
+
+ public <T extends AnnotatedInterfaceConfigBeanBuilder<C>> T interfaceClass(Class<?> interfaceClass) {
+ this.interfaceClass = interfaceClass;
+ return (T) this;
+ }
+}
diff --git a/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/beans/factory/annotation/AnnotationInjectedBeanPostProcessor.java b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/beans/factory/annotation/AnnotationInjectedBeanPostProcessor.java
index 53ff695..de56d29 100644
--- a/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/beans/factory/annotation/AnnotationInjectedBeanPostProcessor.java
+++ b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/beans/factory/annotation/AnnotationInjectedBeanPostProcessor.java
@@ -35,6 +35,7 @@ import org.springframework.beans.factory.support.RootBeanDefinition;
import org.springframework.context.EnvironmentAware;
import org.springframework.core.Ordered;
import org.springframework.core.PriorityOrdered;
+import org.springframework.core.annotation.AnnotationAttributes;
import org.springframework.core.env.Environment;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
@@ -56,20 +57,20 @@ import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
-import static org.apache.dubbo.config.spring.util.ClassUtils.resolveGenericType;
+import static org.apache.dubbo.config.spring.util.AnnotationUtils.getMergedAttributes;
import static org.springframework.core.BridgeMethodResolver.findBridgedMethod;
import static org.springframework.core.BridgeMethodResolver.isVisibilityBridgeMethodPair;
-import static org.springframework.core.annotation.AnnotationUtils.findAnnotation;
-import static org.springframework.core.annotation.AnnotationUtils.getAnnotation;
+import static org.springframework.util.CollectionUtils.isEmpty;
/**
* Abstract generic {@link BeanPostProcessor} implementation for customized annotation that annotated injected-object.
- *
+ * <p>
* The source code is cloned from https://github.com/alibaba/spring-context-support/blob/1.0.2/src/main/java/com/alibaba/spring/beans/factory/annotation/AnnotationInjectedBeanPostProcessor.java
*
+ * @revision 2.7.3 Uses {@link AnnotationAttributes} instead of {@link Annotation}
* @since 2.6.6
*/
-public abstract class AnnotationInjectedBeanPostProcessor<A extends Annotation> extends
+public abstract class AnnotationInjectedBeanPostProcessor extends
InstantiationAwareBeanPostProcessorAdapter implements MergedBeanDefinitionPostProcessor, PriorityOrdered,
BeanFactoryAware, BeanClassLoaderAware, EnvironmentAware, DisposableBean {
@@ -77,7 +78,7 @@ public abstract class AnnotationInjectedBeanPostProcessor<A extends Annotation>
private final Log logger = LogFactory.getLog(getClass());
- private final Class<A> annotationType;
+ private final Class<? extends Annotation>[] annotationTypes;
private final ConcurrentMap<String, AnnotationInjectedBeanPostProcessor.AnnotatedInjectionMetadata> injectionMetadataCache =
new ConcurrentHashMap<String, AnnotationInjectedBeanPostProcessor.AnnotatedInjectionMetadata>(CACHE_SIZE);
@@ -92,8 +93,13 @@ public abstract class AnnotationInjectedBeanPostProcessor<A extends Annotation>
private int order = Ordered.LOWEST_PRECEDENCE;
- public AnnotationInjectedBeanPostProcessor() {
- this.annotationType = resolveGenericType(getClass());
+ /**
+ * @param annotationTypes the multiple types of {@link Annotation annotations}
+ * @since 2.7.3
+ */
+ public AnnotationInjectedBeanPostProcessor(Class<? extends Annotation>... annotationTypes) {
+ Assert.notEmpty(annotationTypes, "The argument of annotations' types must not empty");
+ this.annotationTypes = annotationTypes;
}
@SafeVarargs
@@ -109,9 +115,15 @@ public abstract class AnnotationInjectedBeanPostProcessor<A extends Annotation>
* Annotation type
*
* @return non-null
+ * @deprecated 2.7.3, uses {@link #getAnnotationTypes()}
*/
- public final Class<A> getAnnotationType() {
- return annotationType;
+ @Deprecated
+ public final Class<? extends Annotation> getAnnotationType() {
+ return annotationTypes[0];
+ }
+
+ protected final Class<? extends Annotation>[] getAnnotationTypes() {
+ return annotationTypes;
}
@Override
@@ -131,7 +143,7 @@ public abstract class AnnotationInjectedBeanPostProcessor<A extends Annotation>
} catch (BeanCreationException ex) {
throw ex;
} catch (Throwable ex) {
- throw new BeanCreationException(beanName, "Injection of @" + getAnnotationType().getName()
+ throw new BeanCreationException(beanName, "Injection of @" + getAnnotationType().getSimpleName()
+ " dependencies is failed", ex);
}
return pvs;
@@ -139,7 +151,7 @@ public abstract class AnnotationInjectedBeanPostProcessor<A extends Annotation>
/**
- * Finds {@link InjectionMetadata.InjectedElement} Metadata from annotated {@link A} fields
+ * Finds {@link InjectionMetadata.InjectedElement} Metadata from annotated fields
*
* @param beanClass The {@link Class} of Bean
* @return non-null {@link List}
@@ -150,20 +162,22 @@ public abstract class AnnotationInjectedBeanPostProcessor<A extends Annotation>
ReflectionUtils.doWithFields(beanClass, field -> {
- A annotation = getAnnotation(field, getAnnotationType());
+ for (Class<? extends Annotation> annotationType : getAnnotationTypes()) {
+
+ AnnotationAttributes attributes = getMergedAttributes(field, annotationType, getEnvironment(), true);
- if (annotation != null) {
+ if (!isEmpty(attributes)) {
- if (Modifier.isStatic(field.getModifiers())) {
- if (logger.isWarnEnabled()) {
- logger.warn("@" + getAnnotationType().getName() + " is not supported on static fields: " + field);
+ if (Modifier.isStatic(field.getModifiers())) {
+ if (logger.isWarnEnabled()) {
+ logger.warn("@" + annotationType.getName() + " is not supported on static fields: " + field);
+ }
+ return;
}
- return;
- }
- elements.add(new AnnotatedFieldElement(field, annotation));
+ elements.add(new AnnotatedFieldElement(field, attributes));
+ }
}
-
});
return elements;
@@ -171,7 +185,7 @@ public abstract class AnnotationInjectedBeanPostProcessor<A extends Annotation>
}
/**
- * Finds {@link InjectionMetadata.InjectedElement} Metadata from annotated {@link A @A} methods
+ * Finds {@link InjectionMetadata.InjectedElement} Metadata from annotated methods
*
* @param beanClass The {@link Class} of Bean
* @return non-null {@link List}
@@ -188,23 +202,27 @@ public abstract class AnnotationInjectedBeanPostProcessor<A extends Annotation>
return;
}
- A annotation = findAnnotation(bridgedMethod, getAnnotationType());
- if (annotation != null && method.equals(ClassUtils.getMostSpecificMethod(method, beanClass))) {
- if (Modifier.isStatic(method.getModifiers())) {
- if (logger.isWarnEnabled()) {
- logger.warn("@" + getAnnotationType().getSimpleName() + " annotation is not supported on static methods: " + method);
+ for (Class<? extends Annotation> annotationType : getAnnotationTypes()) {
+
+ AnnotationAttributes attributes = getMergedAttributes(bridgedMethod, annotationType, getEnvironment(), true);
+
+ if (!isEmpty(attributes) && method.equals(ClassUtils.getMostSpecificMethod(method, beanClass))) {
+ if (Modifier.isStatic(method.getModifiers())) {
+ if (logger.isWarnEnabled()) {
+ logger.warn("@" + annotationType.getName() + " annotation is not supported on static methods: " + method);
+ }
+ return;
}
- return;
- }
- if (method.getParameterTypes().length == 0) {
- if (logger.isWarnEnabled()) {
- logger.warn("@" + getAnnotationType().getSimpleName() + " annotation should only be used on methods with parameters: " +
- method);
+ if (method.getParameterTypes().length == 0) {
+ if (logger.isWarnEnabled()) {
+ logger.warn("@" + annotationType.getName() + " annotation should only be used on methods with parameters: " +
+ method);
+ }
}
+ PropertyDescriptor pd = BeanUtils.findPropertyForMethod(bridgedMethod, beanClass);
+ elements.add(new AnnotatedMethodElement(method, pd, attributes));
}
- PropertyDescriptor pd = BeanUtils.findPropertyForMethod(bridgedMethod, beanClass);
- elements.add(new AnnotatedMethodElement(method, pd, annotation));
}
});
@@ -316,9 +334,9 @@ public abstract class AnnotationInjectedBeanPostProcessor<A extends Annotation>
}
/**
- * Get injected-object from specified {@link A annotation} and Bean Class
+ * Get injected-object from specified {@link AnnotationAttributes annotation attributes} and Bean Class
*
- * @param annotation {@link A annotation}
+ * @param attributes {@link AnnotationAttributes the annotation attributes}
* @param bean Current bean that will be injected
* @param beanName Current bean name that will be injected
* @param injectedType the type of injected-object
@@ -326,15 +344,15 @@ public abstract class AnnotationInjectedBeanPostProcessor<A extends Annotation>
* @return An injected object
* @throws Exception If getting is failed
*/
- protected Object getInjectedObject(A annotation, Object bean, String beanName, Class<?> injectedType,
+ protected Object getInjectedObject(AnnotationAttributes attributes, Object bean, String beanName, Class<?> injectedType,
InjectionMetadata.InjectedElement injectedElement) throws Exception {
- String cacheKey = buildInjectedObjectCacheKey(annotation, bean, beanName, injectedType, injectedElement);
+ String cacheKey = buildInjectedObjectCacheKey(attributes, bean, beanName, injectedType, injectedElement);
Object injectedObject = injectedObjectsCache.get(cacheKey);
if (injectedObject == null) {
- injectedObject = doGetInjectedBean(annotation, bean, beanName, injectedType, injectedElement);
+ injectedObject = doGetInjectedBean(attributes, bean, beanName, injectedType, injectedElement);
// Customized inject-object if necessary
injectedObjectsCache.putIfAbsent(cacheKey, injectedObject);
}
@@ -352,7 +370,7 @@ public abstract class AnnotationInjectedBeanPostProcessor<A extends Annotation>
* <li>{@link #getEnvironment() Environment}</li>
* </ul>
*
- * @param annotation {@link A annotation}
+ * @param attributes {@link AnnotationAttributes the annotation attributes}
* @param bean Current bean that will be injected
* @param beanName Current bean name that will be injected
* @param injectedType the type of injected-object
@@ -360,7 +378,7 @@ public abstract class AnnotationInjectedBeanPostProcessor<A extends Annotation>
* @return The injected object
* @throws Exception If resolving an injected object is failed.
*/
- protected abstract Object doGetInjectedBean(A annotation, Object bean, String beanName, Class<?> injectedType,
+ protected abstract Object doGetInjectedBean(AnnotationAttributes attributes, Object bean, String beanName, Class<?> injectedType,
InjectionMetadata.InjectedElement injectedElement) throws Exception;
/**
@@ -372,14 +390,14 @@ public abstract class AnnotationInjectedBeanPostProcessor<A extends Annotation>
* <li>{@link #getEnvironment() Environment}</li>
* </ul>
*
- * @param annotation {@link A annotation}
+ * @param attributes {@link AnnotationAttributes the annotation attributes}
* @param bean Current bean that will be injected
* @param beanName Current bean name that will be injected
* @param injectedType the type of injected-object
* @param injectedElement {@link InjectionMetadata.InjectedElement}
* @return Bean cache key
*/
- protected abstract String buildInjectedObjectCacheKey(A annotation, Object bean, String beanName,
+ protected abstract String buildInjectedObjectCacheKey(AnnotationAttributes attributes, Object bean, String beanName,
Class<?> injectedType,
InjectionMetadata.InjectedElement injectedElement);
@@ -436,7 +454,7 @@ public abstract class AnnotationInjectedBeanPostProcessor<A extends Annotation>
}
/**
- * {@link A} {@link InjectionMetadata} implementation
+ * {@link Annotation Annotated} {@link InjectionMetadata} implementation
*/
private class AnnotatedInjectionMetadata extends InjectionMetadata {
@@ -461,20 +479,20 @@ public abstract class AnnotationInjectedBeanPostProcessor<A extends Annotation>
}
/**
- * {@link A} {@link Method} {@link InjectionMetadata.InjectedElement}
+ * {@link Annotation Annotated} {@link Method} {@link InjectionMetadata.InjectedElement}
*/
private class AnnotatedMethodElement extends InjectionMetadata.InjectedElement {
private final Method method;
- private final A annotation;
+ private final AnnotationAttributes attributes;
private volatile Object object;
- protected AnnotatedMethodElement(Method method, PropertyDescriptor pd, A annotation) {
+ protected AnnotatedMethodElement(Method method, PropertyDescriptor pd, AnnotationAttributes attributes) {
super(method, pd);
this.method = method;
- this.annotation = annotation;
+ this.attributes = attributes;
}
@Override
@@ -482,7 +500,7 @@ public abstract class AnnotationInjectedBeanPostProcessor<A extends Annotation>
Class<?> injectedType = pd.getPropertyType();
- Object injectedObject = getInjectedObject(annotation, bean, beanName, injectedType, this);
+ Object injectedObject = getInjectedObject(attributes, bean, beanName, injectedType, this);
ReflectionUtils.makeAccessible(method);
@@ -493,20 +511,20 @@ public abstract class AnnotationInjectedBeanPostProcessor<A extends Annotation>
}
/**
- * {@link A} {@link Field} {@link InjectionMetadata.InjectedElement}
+ * {@link Annotation Annotated} {@link Field} {@link InjectionMetadata.InjectedElement}
*/
public class AnnotatedFieldElement extends InjectionMetadata.InjectedElement {
private final Field field;
- private final A annotation;
+ private final AnnotationAttributes attributes;
private volatile Object bean;
- protected AnnotatedFieldElement(Field field, A annotation) {
+ protected AnnotatedFieldElement(Field field, AnnotationAttributes attributes) {
super(field, null);
this.field = field;
- this.annotation = annotation;
+ this.attributes = attributes;
}
@Override
@@ -514,7 +532,7 @@ public abstract class AnnotationInjectedBeanPostProcessor<A extends Annotation>
Class<?> injectedType = field.getType();
- Object injectedObject = getInjectedObject(annotation, bean, beanName, injectedType, this);
+ Object injectedObject = getInjectedObject(attributes, bean, beanName, injectedType, this);
ReflectionUtils.makeAccessible(field);
diff --git a/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/beans/factory/annotation/AnnotationPropertyValuesAdapter.java b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/beans/factory/annotation/AnnotationPropertyValuesAdapter.java
index b051d35..5566c39 100644
--- a/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/beans/factory/annotation/AnnotationPropertyValuesAdapter.java
+++ b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/beans/factory/annotation/AnnotationPropertyValuesAdapter.java
@@ -22,8 +22,10 @@ import org.springframework.beans.PropertyValues;
import org.springframework.core.env.PropertyResolver;
import java.lang.annotation.Annotation;
+import java.util.Map;
import static org.apache.dubbo.config.spring.util.AnnotationUtils.getAttributes;
+import static org.apache.dubbo.config.spring.util.AnnotationUtils.resolvePlaceholders;
/**
* {@link Annotation} {@link PropertyValues} Adapter
@@ -34,35 +36,26 @@ import static org.apache.dubbo.config.spring.util.AnnotationUtils.getAttributes;
*/
class AnnotationPropertyValuesAdapter implements PropertyValues {
- private final Annotation annotation;
-
- private final PropertyResolver propertyResolver;
-
- private final boolean ignoreDefaultValue;
-
private final PropertyValues delegate;
- public AnnotationPropertyValuesAdapter(Annotation annotation, PropertyResolver propertyResolver, boolean ignoreDefaultValue, String... ignoreAttributeNames) {
- this.annotation = annotation;
- this.propertyResolver = propertyResolver;
- this.ignoreDefaultValue = ignoreDefaultValue;
- this.delegate = adapt(annotation, ignoreDefaultValue, ignoreAttributeNames);
+ /**
+ * @param attributes
+ * @param propertyResolver
+ * @param ignoreAttributeNames
+ * @since 2.7.3
+ */
+ public AnnotationPropertyValuesAdapter(Map<String, Object> attributes, PropertyResolver propertyResolver,
+ String... ignoreAttributeNames) {
+ this.delegate = new MutablePropertyValues(resolvePlaceholders(attributes, propertyResolver, ignoreAttributeNames));
}
- public AnnotationPropertyValuesAdapter(Annotation annotation, PropertyResolver propertyResolver, String... ignoreAttributeNames) {
- this(annotation, propertyResolver, true, ignoreAttributeNames);
+ public AnnotationPropertyValuesAdapter(Annotation annotation, PropertyResolver propertyResolver,
+ boolean ignoreDefaultValue, String... ignoreAttributeNames) {
+ this.delegate = new MutablePropertyValues(getAttributes(annotation, propertyResolver, ignoreDefaultValue, ignoreAttributeNames));
}
- private PropertyValues adapt(Annotation annotation, boolean ignoreDefaultValue, String... ignoreAttributeNames) {
- return new MutablePropertyValues(getAttributes(annotation, propertyResolver, ignoreDefaultValue, ignoreAttributeNames));
- }
-
- public Annotation getAnnotation() {
- return annotation;
- }
-
- public boolean isIgnoreDefaultValue() {
- return ignoreDefaultValue;
+ public AnnotationPropertyValuesAdapter(Annotation annotation, PropertyResolver propertyResolver, String... ignoreAttributeNames) {
+ this(annotation, propertyResolver, true, ignoreAttributeNames);
}
@Override
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 f7cc7b7..d477c58 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
@@ -29,6 +29,7 @@ import org.springframework.context.ApplicationContextAware;
import org.springframework.context.ApplicationEvent;
import org.springframework.context.ApplicationListener;
import org.springframework.context.event.ContextRefreshedEvent;
+import org.springframework.core.annotation.AnnotationAttributes;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationHandler;
@@ -49,8 +50,8 @@ import static org.apache.dubbo.config.spring.beans.factory.annotation.ServiceBea
*
* @since 2.5.7
*/
-public class ReferenceAnnotationBeanPostProcessor extends AnnotationInjectedBeanPostProcessor<Reference>
- implements ApplicationContextAware, ApplicationListener {
+public class ReferenceAnnotationBeanPostProcessor extends AnnotationInjectedBeanPostProcessor implements
+ ApplicationContextAware, ApplicationListener {
/**
* The bean name of {@link ReferenceAnnotationBeanPostProcessor}
@@ -77,6 +78,13 @@ public class ReferenceAnnotationBeanPostProcessor extends AnnotationInjectedBean
private ApplicationContext applicationContext;
/**
+ * To support the legacy annotation that is @com.alibaba.dubbo.config.annotation.Reference since 2.7.3
+ */
+ public ReferenceAnnotationBeanPostProcessor() {
+ super(Reference.class, com.alibaba.dubbo.config.annotation.Reference.class);
+ }
+
+ /**
* Gets all beans of {@link ReferenceBean}
*
* @return non-null read-only {@link Collection}
@@ -107,12 +115,12 @@ public class ReferenceAnnotationBeanPostProcessor extends AnnotationInjectedBean
}
@Override
- protected Object doGetInjectedBean(Reference reference, Object bean, String beanName, Class<?> injectedType,
+ protected Object doGetInjectedBean(AnnotationAttributes attributes, Object bean, String beanName, Class<?> injectedType,
InjectionMetadata.InjectedElement injectedElement) throws Exception {
- String referencedBeanName = buildReferencedBeanName(reference, injectedType);
+ String referencedBeanName = buildReferencedBeanName(attributes, injectedType);
- ReferenceBean referenceBean = buildReferenceBeanIfAbsent(referencedBeanName, reference, injectedType, getClassLoader());
+ ReferenceBean referenceBean = buildReferenceBeanIfAbsent(referencedBeanName, attributes, injectedType, getClassLoader());
cacheInjectedReferenceBean(referenceBean, injectedElement);
@@ -175,22 +183,22 @@ public class ReferenceAnnotationBeanPostProcessor extends AnnotationInjectedBean
}
@Override
- protected String buildInjectedObjectCacheKey(Reference reference, Object bean, String beanName,
+ protected String buildInjectedObjectCacheKey(AnnotationAttributes attributes, Object bean, String beanName,
Class<?> injectedType, InjectionMetadata.InjectedElement injectedElement) {
- return buildReferencedBeanName(reference, injectedType) +
+ return buildReferencedBeanName(attributes, injectedType) +
"#source=" + (injectedElement.getMember()) +
- "#attributes=" + AnnotationUtils.getAttributes(reference, getEnvironment(), true);
+ "#attributes=" + AnnotationUtils.resolvePlaceholders(attributes, getEnvironment());
}
- private String buildReferencedBeanName(Reference reference, Class<?> injectedType) {
+ private String buildReferencedBeanName(AnnotationAttributes attributes, Class<?> injectedType) {
- ServiceBeanNameBuilder serviceBeanNameBuilder = create(reference, injectedType, getEnvironment());
+ ServiceBeanNameBuilder serviceBeanNameBuilder = create(attributes, injectedType, getEnvironment());
return serviceBeanNameBuilder.build();
}
- private ReferenceBean buildReferenceBeanIfAbsent(String referencedBeanName, Reference reference,
+ private ReferenceBean buildReferenceBeanIfAbsent(String referencedBeanName, AnnotationAttributes attributes,
Class<?> referencedType, ClassLoader classLoader)
throws Exception {
@@ -198,7 +206,7 @@ public class ReferenceAnnotationBeanPostProcessor extends AnnotationInjectedBean
if (referenceBean == null) {
ReferenceBeanBuilder beanBuilder = ReferenceBeanBuilder
- .create(reference, classLoader, applicationContext)
+ .create(attributes, applicationContext)
.interfaceClass(referencedType);
referenceBean = beanBuilder.build();
referenceBeanCache.put(referencedBeanName, referenceBean);
diff --git a/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/beans/factory/annotation/ReferenceBeanBuilder.java b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/beans/factory/annotation/ReferenceBeanBuilder.java
index d4aef6a..2054473 100644
--- a/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/beans/factory/annotation/ReferenceBeanBuilder.java
+++ b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/beans/factory/annotation/ReferenceBeanBuilder.java
@@ -25,8 +25,8 @@ import org.apache.dubbo.config.spring.ReferenceBean;
import org.springframework.beans.propertyeditors.StringTrimmerEditor;
import org.springframework.context.ApplicationContext;
+import org.springframework.core.annotation.AnnotationAttributes;
import org.springframework.util.Assert;
-import org.springframework.util.ClassUtils;
import org.springframework.util.StringUtils;
import org.springframework.validation.DataBinder;
@@ -34,8 +34,12 @@ import java.beans.PropertyEditorSupport;
import java.util.List;
import java.util.Map;
+import static org.apache.dubbo.config.spring.util.AnnotationUtils.getAttribute;
+import static org.apache.dubbo.config.spring.util.AnnotationUtils.getAttributes;
+import static org.apache.dubbo.config.spring.util.AnnotationUtils.resolveServiceInterfaceClass;
import static org.apache.dubbo.config.spring.util.BeanFactoryUtils.getOptionalBean;
import static org.apache.dubbo.config.spring.util.ObjectUtils.of;
+import static org.springframework.core.annotation.AnnotationAttributes.fromMap;
import static org.springframework.util.StringUtils.commaDelimitedListToStringArray;
/**
@@ -43,48 +47,30 @@ import static org.springframework.util.StringUtils.commaDelimitedListToStringArr
*
* @since 2.5.7
*/
-class ReferenceBeanBuilder extends AbstractAnnotationConfigBeanBuilder<Reference, ReferenceBean> {
+class ReferenceBeanBuilder extends AnnotatedInterfaceConfigBeanBuilder<ReferenceBean> {
// Ignore those fields
static final String[] IGNORE_FIELD_NAMES = of("application", "module", "consumer", "monitor", "registry");
- private ReferenceBeanBuilder(Reference annotation, ClassLoader classLoader, ApplicationContext applicationContext) {
- super(annotation, classLoader, applicationContext);
+ private ReferenceBeanBuilder(AnnotationAttributes attributes, ApplicationContext applicationContext) {
+ super(attributes, applicationContext);
}
- private void configureInterface(Reference reference, ReferenceBean referenceBean) {
+ private void configureInterface(AnnotationAttributes attributes, ReferenceBean referenceBean) {
- Class<?> interfaceClass = reference.interfaceClass();
+ Class<?> serviceInterfaceClass = resolveServiceInterfaceClass(attributes, interfaceClass);
- if (void.class.equals(interfaceClass)) {
-
- interfaceClass = null;
-
- String interfaceClassName = reference.interfaceName();
-
- if (StringUtils.hasText(interfaceClassName)) {
- if (ClassUtils.isPresent(interfaceClassName, classLoader)) {
- interfaceClass = ClassUtils.resolveClassName(interfaceClassName, classLoader);
- }
- }
-
- }
-
- if (interfaceClass == null) {
- interfaceClass = this.interfaceClass;
- }
-
- Assert.isTrue(interfaceClass.isInterface(),
+ Assert.isTrue(serviceInterfaceClass.isInterface(),
"The class of field or method that was annotated @Reference is not an interface!");
- referenceBean.setInterface(interfaceClass);
+ referenceBean.setInterface(serviceInterfaceClass);
}
- private void configureConsumerConfig(Reference reference, ReferenceBean<?> referenceBean) {
+ private void configureConsumerConfig(AnnotationAttributes attributes, ReferenceBean<?> referenceBean) {
- String consumerBeanName = reference.consumer();
+ String consumerBeanName = getAttribute(attributes, "consumer");
ConsumerConfig consumerConfig = getOptionalBean(applicationContext, consumerBeanName, ConsumerConfig.class);
@@ -92,10 +78,10 @@ class ReferenceBeanBuilder extends AbstractAnnotationConfigBeanBuilder<Reference
}
- void configureMethodConfig(Reference reference, ReferenceBean<?> referenceBean){
- Method[] methods = reference.methods();
+ void configureMethodConfig(AnnotationAttributes attributes, ReferenceBean<?> referenceBean) {
+ Method[] methods = (Method[]) attributes.get("methods");
List<MethodConfig> methodConfigs = MethodConfig.constructMethodConfig(methods);
- if(!methodConfigs.isEmpty()){
+ if (!methodConfigs.isEmpty()) {
referenceBean.setMethods(methodConfigs);
}
}
@@ -106,7 +92,7 @@ class ReferenceBeanBuilder extends AbstractAnnotationConfigBeanBuilder<Reference
}
@Override
- protected void preConfigureBean(Reference reference, ReferenceBean referenceBean) {
+ protected void preConfigureBean(AnnotationAttributes attributes, ReferenceBean referenceBean) {
Assert.notNull(interfaceClass, "The interface class must set first!");
DataBinder dataBinder = new DataBinder(referenceBean);
// Register CustomEditors for special fields
@@ -131,49 +117,53 @@ class ReferenceBeanBuilder extends AbstractAnnotationConfigBeanBuilder<Reference
});
// Bind annotation attributes
- dataBinder.bind(new AnnotationPropertyValuesAdapter(reference, applicationContext.getEnvironment(), IGNORE_FIELD_NAMES));
+ dataBinder.bind(new AnnotationPropertyValuesAdapter(attributes, applicationContext.getEnvironment(), IGNORE_FIELD_NAMES));
}
@Override
- protected String resolveModuleConfigBeanName(Reference annotation) {
- return annotation.module();
+ protected String resolveModuleConfigBeanName(AnnotationAttributes attributes) {
+ return getAttribute(attributes, "module");
}
@Override
- protected String resolveApplicationConfigBeanName(Reference annotation) {
- return annotation.application();
+ protected String resolveApplicationConfigBeanName(AnnotationAttributes attributes) {
+ return getAttribute(attributes, "application");
}
@Override
- protected String[] resolveRegistryConfigBeanNames(Reference annotation) {
- return annotation.registry();
+ protected String[] resolveRegistryConfigBeanNames(AnnotationAttributes attributes) {
+ return getAttribute(attributes, "registry");
}
@Override
- protected String resolveMonitorConfigBeanName(Reference annotation) {
- return annotation.monitor();
+ protected String resolveMonitorConfigBeanName(AnnotationAttributes attributes) {
+ return getAttribute(attributes, "monitor");
}
@Override
- protected void postConfigureBean(Reference annotation, ReferenceBean bean) throws Exception {
+ protected void postConfigureBean(AnnotationAttributes attributes, ReferenceBean bean) throws Exception {
bean.setApplicationContext(applicationContext);
- configureInterface(annotation, bean);
+ configureInterface(attributes, bean);
- configureConsumerConfig(annotation, bean);
+ configureConsumerConfig(attributes, bean);
- configureMethodConfig(annotation, bean);
+ configureMethodConfig(attributes, bean);
bean.afterPropertiesSet();
}
- public static ReferenceBeanBuilder create(Reference annotation, ClassLoader classLoader,
+ @Deprecated
+ public static ReferenceBeanBuilder create(Reference reference, ClassLoader classLoader,
ApplicationContext applicationContext) {
- return new ReferenceBeanBuilder(annotation, classLoader, applicationContext);
+ return create(fromMap(getAttributes(reference, applicationContext.getEnvironment(), true)), applicationContext);
}
+ public static ReferenceBeanBuilder create(AnnotationAttributes attributes, ApplicationContext applicationContext) {
+ return new ReferenceBeanBuilder(attributes, applicationContext);
+ }
}
diff --git a/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/beans/factory/annotation/ServiceAnnotationBeanPostProcessor.java b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/beans/factory/annotation/ServiceAnnotationBeanPostProcessor.java
index 0edc5f3..06deb57 100644
--- a/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/beans/factory/annotation/ServiceAnnotationBeanPostProcessor.java
+++ b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/beans/factory/annotation/ServiceAnnotationBeanPostProcessor.java
@@ -65,7 +65,7 @@ import static org.apache.dubbo.config.spring.util.AnnotationUtils.resolveService
import static org.apache.dubbo.config.spring.util.ObjectUtils.of;
import static org.springframework.beans.factory.support.BeanDefinitionBuilder.rootBeanDefinition;
import static org.springframework.context.annotation.AnnotationConfigUtils.CONFIGURATION_BEAN_NAME_GENERATOR;
-import static org.springframework.core.annotation.AnnotationUtils.findAnnotation;
+import static org.springframework.core.annotation.AnnotatedElementUtils.findMergedAnnotation;
import static org.springframework.core.annotation.AnnotationUtils.getAnnotationAttributes;
import static org.springframework.util.ClassUtils.resolveClassName;
@@ -306,9 +306,9 @@ public class ServiceAnnotationBeanPostProcessor implements BeanDefinitionRegistr
* @since 2.7.3
*/
private Annotation findServiceAnnotation(Class<?> beanClass) {
- Annotation service = findAnnotation(beanClass, Service.class);
+ Annotation service = findMergedAnnotation(beanClass, Service.class);
if (service == null) {
- service = findAnnotation(beanClass, com.alibaba.dubbo.config.annotation.Service.class);
+ service = findMergedAnnotation(beanClass, com.alibaba.dubbo.config.annotation.Service.class);
}
return service;
}
diff --git a/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/beans/factory/annotation/ServiceBeanNameBuilder.java b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/beans/factory/annotation/ServiceBeanNameBuilder.java
index 390e0b6..8aef87f 100644
--- a/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/beans/factory/annotation/ServiceBeanNameBuilder.java
+++ b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/beans/factory/annotation/ServiceBeanNameBuilder.java
@@ -25,6 +25,7 @@ import org.springframework.core.annotation.AnnotationAttributes;
import org.springframework.core.env.Environment;
import org.springframework.util.StringUtils;
+import static org.apache.dubbo.config.spring.util.AnnotationUtils.getAttribute;
import static org.apache.dubbo.config.spring.util.AnnotationUtils.resolveInterfaceName;
import static org.springframework.core.annotation.AnnotationUtils.getAnnotationAttributes;
@@ -62,8 +63,8 @@ public class ServiceBeanNameBuilder {
private ServiceBeanNameBuilder(AnnotationAttributes attributes, Class<?> defaultInterfaceClass, Environment environment) {
this(resolveInterfaceName(attributes, defaultInterfaceClass), environment);
- this.group(attributes.getString("group"));
- this.version(attributes.getString("version"));
+ this.group(getAttribute(attributes,"group"));
+ this.version(getAttribute(attributes,"version"));
}
/**
diff --git a/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/util/AnnotatedBeanDefinitionRegistryUtils.java b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/util/AnnotatedBeanDefinitionRegistryUtils.java
index bf065f8..c46ca8a 100644
--- a/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/util/AnnotatedBeanDefinitionRegistryUtils.java
+++ b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/util/AnnotatedBeanDefinitionRegistryUtils.java
@@ -18,18 +18,27 @@ package org.apache.dubbo.config.spring.util;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
+import org.springframework.beans.factory.annotation.AnnotatedBeanDefinition;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.context.annotation.AnnotatedBeanDefinitionReader;
+import org.springframework.core.type.AnnotationMetadata;
import org.springframework.util.ObjectUtils;
import java.lang.annotation.Annotation;
-import java.util.Arrays;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.Objects;
+
+import static java.lang.String.format;
+import static java.util.Arrays.asList;
+import static org.springframework.util.ClassUtils.resolveClassName;
/**
* Annotated {@link BeanDefinition} Utilities
* <p>
* The source code is cloned from https://github.com/alibaba/spring-context-support/blob/1.0.2/src/main/java/com/alibaba/spring/util/AnnotatedBeanDefinitionRegistryUtils.java
+ *
* @since 2.6.6
*/
public abstract class AnnotatedBeanDefinitionRegistryUtils {
@@ -37,10 +46,47 @@ public abstract class AnnotatedBeanDefinitionRegistryUtils {
private static final Log logger = LogFactory.getLog(AnnotatedBeanDefinitionRegistryUtils.class);
/**
- * Register Beans
+ * Is present bean that was registered by the specified {@link Annotation annotated} {@link Class class}
+ *
+ * @param registry {@link BeanDefinitionRegistry}
+ * @param annotatedClass the {@link Annotation annotated} {@link Class class}
+ * @return if present, return <code>true</code>, or <code>false</code>
+ * @since 2.7.3
+ */
+ public static boolean isPresentBean(BeanDefinitionRegistry registry, Class<?> annotatedClass) {
+
+ boolean present = false;
+
+ String[] beanNames = registry.getBeanDefinitionNames();
+
+ ClassLoader classLoader = annotatedClass.getClassLoader();
+
+ for (String beanName : beanNames) {
+ BeanDefinition beanDefinition = registry.getBeanDefinition(beanName);
+ if (beanDefinition instanceof AnnotatedBeanDefinition) {
+ AnnotationMetadata annotationMetadata = ((AnnotatedBeanDefinition) beanDefinition).getMetadata();
+ String className = annotationMetadata.getClassName();
+ Class<?> targetClass = resolveClassName(className, classLoader);
+ present = Objects.equals(targetClass, annotatedClass);
+ if (present) {
+ if (logger.isDebugEnabled()) {
+ logger.debug(format("The annotatedClass[class : %s , bean name : %s] was present in registry[%s]",
+ className, beanName, registry));
+ }
+ break;
+ }
+ }
+ }
+
+ return present;
+ }
+
+ /**
+ * Register Beans if not present in {@link BeanDefinitionRegistry registry}
*
* @param registry {@link BeanDefinitionRegistry}
* @param annotatedClasses {@link Annotation annotation} class
+ * @revision 2.7.3 {@link #isPresentBean(BeanDefinitionRegistry, Class)}
*/
public static void registerBeans(BeanDefinitionRegistry registry, Class<?>... annotatedClasses) {
@@ -50,10 +96,20 @@ public abstract class AnnotatedBeanDefinitionRegistryUtils {
boolean debugEnabled = logger.isDebugEnabled();
+ // Remove all annotated-classes that have been registered
+ Iterator<Class<?>> iterator = new ArrayList<>(asList(annotatedClasses)).iterator();
+
+ while (iterator.hasNext()) {
+ Class<?> annotatedClass = iterator.next();
+ if (isPresentBean(registry, annotatedClass)) {
+ iterator.remove();
+ }
+ }
+
AnnotatedBeanDefinitionReader reader = new AnnotatedBeanDefinitionReader(registry);
if (debugEnabled) {
- logger.debug(registry.getClass().getSimpleName() + " will register annotated classes : " + Arrays.asList(annotatedClasses) + " .");
+ logger.debug(registry.getClass().getSimpleName() + " will register annotated classes : " + asList(annotatedClasses) + " .");
}
reader.register(annotatedClasses);
diff --git a/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/util/AnnotationUtils.java b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/util/AnnotationUtils.java
index 600c1b7..3b308d3 100644
--- a/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/util/AnnotationUtils.java
+++ b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/util/AnnotationUtils.java
@@ -30,22 +30,26 @@ import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
+import java.lang.reflect.AnnotatedElement;
import java.lang.reflect.Method;
import java.util.Collections;
-import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
-import java.util.Set;
import static java.lang.String.valueOf;
+import static java.util.Collections.emptyMap;
+import static java.util.Collections.unmodifiableMap;
+import static org.springframework.core.annotation.AnnotatedElementUtils.getMergedAnnotation;
+import static org.springframework.core.annotation.AnnotationAttributes.fromMap;
import static org.springframework.core.annotation.AnnotationUtils.findAnnotation;
import static org.springframework.core.annotation.AnnotationUtils.getAnnotationAttributes;
import static org.springframework.core.annotation.AnnotationUtils.getDefaultValue;
import static org.springframework.util.ClassUtils.getAllInterfacesForClass;
import static org.springframework.util.ClassUtils.resolveClassName;
-import static org.springframework.util.CollectionUtils.arrayToList;
+import static org.springframework.util.CollectionUtils.isEmpty;
+import static org.springframework.util.ObjectUtils.containsElement;
import static org.springframework.util.ObjectUtils.nullSafeEquals;
import static org.springframework.util.StringUtils.hasText;
import static org.springframework.util.StringUtils.trimWhitespace;
@@ -89,46 +93,43 @@ public class AnnotationUtils {
* @throws IllegalStateException if interface name was not found
*/
public static String resolveInterfaceName(AnnotationAttributes attributes, Class<?> defaultInterfaceClass) {
+ return resolveServiceInterfaceClass(attributes, defaultInterfaceClass).getName();
+ }
- String interfaceName = null;
-
- Class<?> interfaceClass = attributes.getClass("interfaceClass");
- if (interfaceClass != null && !void.class.equals(interfaceClass)) {
- interfaceName = interfaceClass.getName();
- } else if ((!hasText(interfaceName = attributes.getString("interfaceName")))) {
- interfaceName = defaultInterfaceClass.isInterface() ? defaultInterfaceClass.getName() : null;
- }
-
- if (!hasText(interfaceName)) {
- throw new IllegalStateException(
- "The @Service undefined interfaceClass or interfaceName, and the type "
- + defaultInterfaceClass.getName() + " is not a interface.");
- }
-
- return interfaceName;
+ /**
+ * Get the attribute value
+ *
+ * @param attributes {@link AnnotationAttributes the annotation attributes}
+ * @param name the name of attribute
+ * @param <T> the type of attribute value
+ * @return the attribute value if found
+ * @since 2.7.3
+ */
+ public static <T> T getAttribute(AnnotationAttributes attributes, String name) {
+ return (T) attributes.get(name);
}
/**
* Resolve the {@link Class class} of Dubbo Service interface from the specified
* {@link AnnotationAttributes annotation attributes} and annotated {@link Class class}.
*
- * @param attributes {@link AnnotationAttributes annotation attributes}
- * @param annotatedClass the annotated {@link Class class}.
+ * @param attributes {@link AnnotationAttributes annotation attributes}
+ * @param defaultInterfaceClass the annotated {@link Class class}.
* @return the {@link Class class} of Dubbo Service interface
* @throws IllegalArgumentException if can't resolved
*/
- public static Class<?> resolveServiceInterfaceClass(AnnotationAttributes attributes, Class<?> annotatedClass)
+ public static Class<?> resolveServiceInterfaceClass(AnnotationAttributes attributes, Class<?> defaultInterfaceClass)
throws IllegalArgumentException {
- ClassLoader classLoader = annotatedClass.getClassLoader();
+ ClassLoader classLoader = defaultInterfaceClass != null ? defaultInterfaceClass.getClassLoader() : Thread.currentThread().getContextClassLoader();
- Class<?> interfaceClass = attributes.getClass("interfaceClass");
+ Class<?> interfaceClass = getAttribute(attributes, "interfaceClass");
if (void.class.equals(interfaceClass)) { // default or set void.class for purpose.
interfaceClass = null;
- String interfaceClassName = attributes.getString("interfaceName");
+ String interfaceClassName = getAttribute(attributes, "interfaceName");
if (hasText(interfaceClassName)) {
if (ClassUtils.isPresent(interfaceClassName, classLoader)) {
@@ -138,10 +139,10 @@ public class AnnotationUtils {
}
- if (interfaceClass == null) {
+ if (interfaceClass == null && defaultInterfaceClass != null) {
// Find all interfaces from the annotated class
// To resolve an issue : https://github.com/apache/dubbo/issues/3251
- Class<?>[] allInterfaces = getAllInterfacesForClass(annotatedClass);
+ Class<?>[] allInterfaces = getAllInterfacesForClass(defaultInterfaceClass);
if (allInterfaces.length > 0) {
interfaceClass = allInterfaces[0];
@@ -153,7 +154,7 @@ public class AnnotationUtils {
"@Service interfaceClass() or interfaceName() or interface class must be present!");
Assert.isTrue(interfaceClass.isInterface(),
- "The type that was annotated @Service is not an interface!");
+ "The annotated type must be an interface!");
return interfaceClass;
}
@@ -292,7 +293,7 @@ public class AnnotationUtils {
}
- return Collections.unmodifiableMap(annotationsMap);
+ return unmodifiableMap(annotationsMap);
}
@@ -304,7 +305,9 @@ public class AnnotationUtils {
* @param ignoreAttributeNames the attribute names of annotation should be ignored
* @return non-null
* @since 2.6.6
+ * @deprecated
*/
+ @Deprecated
public static Map<String, Object> getAttributes(Annotation annotation, boolean ignoreDefaultValue,
String... ignoreAttributeNames) {
return getAttributes(annotation, null, ignoreDefaultValue, ignoreAttributeNames);
@@ -323,11 +326,13 @@ public class AnnotationUtils {
public static Map<String, Object> getAttributes(Annotation annotation, PropertyResolver propertyResolver,
boolean ignoreDefaultValue, String... ignoreAttributeNames) {
- Set<String> ignoreAttributeNamesSet = new HashSet<String>(arrayToList(ignoreAttributeNames));
+ if (annotation == null) {
+ return emptyMap();
+ }
Map<String, Object> attributes = getAnnotationAttributes(annotation);
- Map<String, Object> actualAttributes = new LinkedHashMap<String, Object>();
+ Map<String, Object> actualAttributes = new LinkedHashMap<>();
for (Map.Entry<String, Object> entry : attributes.entrySet()) {
@@ -339,11 +344,6 @@ public class AnnotationUtils {
continue;
}
- // ignore attribute name
- if (ignoreAttributeNamesSet.contains(attributeName)) {
- continue;
- }
-
/**
* @since 2.7.1
* ignore annotation member
@@ -354,6 +354,42 @@ public class AnnotationUtils {
if (attributeValue.getClass().isArray() && attributeValue.getClass().getComponentType().isAnnotation()) {
continue;
}
+ actualAttributes.put(attributeName, attributeValue);
+ }
+
+
+ return resolvePlaceholders(actualAttributes, propertyResolver, ignoreAttributeNames);
+ }
+
+ /**
+ * Resolve the placeholders from the specified annotation attributes
+ *
+ * @param sourceAnnotationAttributes the source of annotation attributes
+ * @param propertyResolver {@link PropertyResolver}
+ * @param ignoreAttributeNames the attribute names to be ignored
+ * @return a new resolved annotation attributes , non-null and read-only
+ * @since 2.7.3
+ */
+ public static Map<String, Object> resolvePlaceholders(Map<String, Object> sourceAnnotationAttributes,
+ PropertyResolver propertyResolver,
+ String... ignoreAttributeNames) {
+
+ if (isEmpty(sourceAnnotationAttributes)) {
+ return emptyMap();
+ }
+
+ Map<String, Object> resolvedAnnotationAttributes = new LinkedHashMap<>();
+
+ for (Map.Entry<String, Object> entry : sourceAnnotationAttributes.entrySet()) {
+
+ String attributeName = entry.getKey();
+
+ // ignore attribute name to skip
+ if (containsElement(ignoreAttributeNames, attributeName)) {
+ continue;
+ }
+
+ Object attributeValue = entry.getValue();
if (attributeValue instanceof String) {
attributeValue = resolvePlaceholders(valueOf(attributeValue), propertyResolver);
@@ -364,9 +400,32 @@ public class AnnotationUtils {
}
attributeValue = values;
}
- actualAttributes.put(attributeName, attributeValue);
+
+ resolvedAnnotationAttributes.put(attributeName, attributeValue);
}
- return actualAttributes;
+
+ return unmodifiableMap(resolvedAnnotationAttributes);
+ }
+
+ /**
+ * Get {@link AnnotationAttributes the annotation attributes} after merging and resolving the placeholders
+ *
+ * @param annotatedElement {@link AnnotatedElement the annotated element}
+ * @param annotationType the {@link Class tyoe} pf {@link Annotation annotation}
+ * @param propertyResolver {@link PropertyResolver} instance, e.g {@link Environment}
+ * @param ignoreDefaultValue whether ignore default value or not
+ * @param ignoreAttributeNames the attribute names of annotation should be ignored
+ * @return non-null
+ * @since 2.7.3
+ */
+ public static AnnotationAttributes getMergedAttributes(AnnotatedElement annotatedElement,
+ Class<? extends Annotation> annotationType,
+ PropertyResolver propertyResolver,
+ boolean ignoreDefaultValue,
+ String... ignoreAttributeNames) {
+ Annotation annotation = getMergedAnnotation(annotatedElement, annotationType);
+ return fromMap(getAttributes(annotation, propertyResolver, ignoreDefaultValue, ignoreAttributeNames));
+
}
private static String resolvePlaceholders(String attributeValue, PropertyResolver propertyResolver) {
diff --git a/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/util/BeanFactoryUtils.java b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/util/BeanFactoryUtils.java
index 71fb767..558986e 100644
--- a/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/util/BeanFactoryUtils.java
+++ b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/util/BeanFactoryUtils.java
@@ -29,9 +29,11 @@ import java.util.Collections;
import java.util.List;
import java.util.Map;
+import static java.util.Collections.emptyList;
import static org.springframework.beans.factory.BeanFactoryUtils.beanNamesForTypeIncludingAncestors;
import static org.springframework.beans.factory.BeanFactoryUtils.beansOfTypeIncludingAncestors;
import static org.springframework.util.ObjectUtils.containsElement;
+import static org.springframework.util.ObjectUtils.isEmpty;
/**
* {@link BeanFactory} Utilities class
@@ -104,6 +106,10 @@ public class BeanFactoryUtils {
*/
public static <T> List<T> getBeans(ListableBeanFactory beanFactory, String[] beanNames, Class<T> beanType) {
+ if (isEmpty(beanNames)) {
+ return emptyList();
+ }
+
String[] allBeanNames = beanNamesForTypeIncludingAncestors(beanFactory, beanType);
List<T> beans = new ArrayList<T>(beanNames.length);
diff --git a/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/context/context/annotation/provider/DefaultHelloService.java b/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/annotation/merged/MergedReference.java
similarity index 52%
copy from dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/context/context/annotation/provider/DefaultHelloService.java
copy to dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/annotation/merged/MergedReference.java
index b484d26..9d34077 100644
--- a/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/context/context/annotation/provider/DefaultHelloService.java
+++ b/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/annotation/merged/MergedReference.java
@@ -14,25 +14,28 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.apache.dubbo.config.spring.context.context.annotation.provider;
+package org.apache.dubbo.config.spring.annotation.merged;
-import org.apache.dubbo.config.spring.api.HelloService;
-import org.springframework.stereotype.Service;
+import org.apache.dubbo.config.annotation.Reference;
-/**
- * Default {@link HelloService} annotation with Spring's {@link Service}
- * and Dubbo's {@link org.apache.dubbo.config.annotation.Service}
- *
- * @since TODO
- */
-@Service
-@org.apache.dubbo.config.annotation.Service
-public class DefaultHelloService implements HelloService {
+import org.springframework.core.annotation.AliasFor;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+@Documented
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ElementType.FIELD, ElementType.METHOD, ElementType.ANNOTATION_TYPE})
+@Reference
+public @interface MergedReference {
- @Override
- public String sayHello(String name) {
- return "Greeting, " + name;
- }
+ @AliasFor(annotation = Reference.class, attribute = "group")
+ String group() default "dubbo";
+ @AliasFor(annotation = Reference.class, attribute = "version")
+ String version() default "1.0.0";
}
diff --git a/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/context/context/annotation/provider/DefaultHelloService.java b/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/annotation/merged/MergedService.java
similarity index 54%
copy from dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/context/context/annotation/provider/DefaultHelloService.java
copy to dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/annotation/merged/MergedService.java
index b484d26..cfe1243 100644
--- a/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/context/context/annotation/provider/DefaultHelloService.java
+++ b/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/annotation/merged/MergedService.java
@@ -14,25 +14,28 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.apache.dubbo.config.spring.context.context.annotation.provider;
+package org.apache.dubbo.config.spring.annotation.merged;
-import org.apache.dubbo.config.spring.api.HelloService;
-import org.springframework.stereotype.Service;
+import org.apache.dubbo.config.annotation.Service;
-/**
- * Default {@link HelloService} annotation with Spring's {@link Service}
- * and Dubbo's {@link org.apache.dubbo.config.annotation.Service}
- *
- * @since TODO
- */
+import org.springframework.core.annotation.AliasFor;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+@Documented
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ElementType.TYPE})
@Service
-@org.apache.dubbo.config.annotation.Service
-public class DefaultHelloService implements HelloService {
+public @interface MergedService {
- @Override
- public String sayHello(String name) {
- return "Greeting, " + name;
- }
+ @AliasFor(annotation = Service.class, attribute = "group")
+ String group() default "dubbo";
+ @AliasFor(annotation = Service.class, attribute = "version")
+ String version() default "1.0.0";
}
diff --git a/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/beans/factory/annotation/MergedAnnotationTest.java b/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/beans/factory/annotation/MergedAnnotationTest.java
new file mode 100644
index 0000000..48c04eb
--- /dev/null
+++ b/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/beans/factory/annotation/MergedAnnotationTest.java
@@ -0,0 +1,76 @@
+/*
+ * 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.beans.factory.annotation;
+
+import org.apache.dubbo.config.annotation.Reference;
+import org.apache.dubbo.config.annotation.Service;
+import org.apache.dubbo.config.spring.annotation.merged.MergedReference;
+import org.apache.dubbo.config.spring.annotation.merged.MergedService;
+import org.apache.dubbo.config.spring.api.DemoService;
+
+import org.junit.Assert;
+import org.junit.Test;
+import org.springframework.core.annotation.AnnotatedElementUtils;
+import org.springframework.util.ReflectionUtils;
+
+import java.lang.reflect.Field;
+
+public class MergedAnnotationTest {
+
+ @Test
+ public void testMergedReference() {
+ Field field = ReflectionUtils.findField(MergedAnnotationTest.TestBean1.class, "demoService");
+ Reference reference = AnnotatedElementUtils.getMergedAnnotation(field, Reference.class);
+ Assert.assertEquals("dubbo", reference.group());
+ Assert.assertEquals("1.0.0", reference.version());
+
+ Field field2 = ReflectionUtils.findField(MergedAnnotationTest.TestBean2.class, "demoService");
+ Reference reference2 = AnnotatedElementUtils.getMergedAnnotation(field2, Reference.class);
+ Assert.assertEquals("group", reference2.group());
+ Assert.assertEquals("2.0", reference2.version());
+ }
+
+ @Test
+ public void testMergedService() {
+ Service service1 = AnnotatedElementUtils.getMergedAnnotation(MergedAnnotationTest.DemoServiceImpl1.class, Service.class);
+ Assert.assertEquals("dubbo", service1.group());
+ Assert.assertEquals("1.0.0", service1.version());
+
+ Service service2 = AnnotatedElementUtils.getMergedAnnotation(MergedAnnotationTest.DemoServiceImpl2.class, Service.class);
+ Assert.assertEquals("group", service2.group());
+ Assert.assertEquals("2.0", service2.version());
+ }
+
+ @MergedService
+ public static class DemoServiceImpl1 {
+ }
+
+ @MergedService(group = "group", version = "2.0")
+ public static class DemoServiceImpl2 {
+ }
+
+ private static class TestBean1 {
+ @MergedReference
+ private DemoService demoService;
+ }
+
+ private static class TestBean2 {
+ @MergedReference(group = "group", version = "2.0")
+ private DemoService demoService;
+ }
+
+}
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 6f62678..1ee01dc 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
@@ -229,7 +229,7 @@ public class ReferenceAnnotationBeanPostProcessorTest {
return demoService;
}
- @Reference(version = "2.5.7", url = "dubbo://127.0.0.1:12345")
+ @com.alibaba.dubbo.config.annotation.Reference(version = "2.5.7", url = "dubbo://127.0.0.1:12345")
public void setDemoService(DemoService demoService) {
this.demoService = demoService;
}
diff --git a/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/context/context/annotation/provider/DefaultHelloService.java b/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/context/context/annotation/provider/DefaultHelloService.java
index b484d26..8277bc9 100644
--- a/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/context/context/annotation/provider/DefaultHelloService.java
+++ b/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/context/context/annotation/provider/DefaultHelloService.java
@@ -16,6 +16,7 @@
*/
package org.apache.dubbo.config.spring.context.context.annotation.provider;
+import org.apache.dubbo.config.spring.annotation.merged.MergedService;
import org.apache.dubbo.config.spring.api.HelloService;
import org.springframework.stereotype.Service;
@@ -27,7 +28,8 @@ import org.springframework.stereotype.Service;
* @since TODO
*/
@Service
-@org.apache.dubbo.config.annotation.Service
+//@org.apache.dubbo.config.annotation.Service
+@MergedService
public class DefaultHelloService implements HelloService {
@Override
diff --git a/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/util/AnnotatedBeanDefinitionRegistryUtilsTest.java b/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/util/AnnotatedBeanDefinitionRegistryUtilsTest.java
new file mode 100644
index 0000000..05c4a78
--- /dev/null
+++ b/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/util/AnnotatedBeanDefinitionRegistryUtilsTest.java
@@ -0,0 +1,74 @@
+/*
+ * 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.junit.Assert;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.Test;
+import org.springframework.context.annotation.AnnotationConfigApplicationContext;
+import org.springframework.stereotype.Service;
+
+import static org.apache.dubbo.config.spring.util.AnnotatedBeanDefinitionRegistryUtils.isPresentBean;
+import static org.apache.dubbo.config.spring.util.AnnotatedBeanDefinitionRegistryUtils.registerBeans;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+/**
+ * {@link AnnotatedBeanDefinitionRegistryUtils} Test
+ *
+ * @since 2.7.3
+ */
+public class AnnotatedBeanDefinitionRegistryUtilsTest {
+
+ private AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
+
+ @AfterEach
+ public void destroy() {
+ context.close();
+ }
+
+ @Test
+ public void testIsPresentBean() {
+
+ assertFalse(isPresentBean(context, A.class));
+
+ context.register(A.class);
+
+ for (int i = 0; i < 9; i++) {
+ assertTrue(isPresentBean(context, A.class));
+ }
+
+ }
+
+ @Test
+ public void testRegisterBeans() {
+
+ registerBeans(context, A.class, A.class);
+
+ context.refresh();
+
+ A a = context.getBean(A.class);
+
+ Assert.assertNotNull(a);
+ }
+
+
+ @Service
+ static class A {
+
+ }
+}