From fb0911de9745fe3e6c6013e47739536d07c23896 Mon Sep 17 00:00:00 2001 From: huazhongming Date: Tue, 26 Sep 2023 10:34:30 +0800 Subject: [PATCH] Clear ReferenceAnnotationWithAotBeanPostProcessor logic (#13098) Signed-off-by: crazyhzm --- .../ReferenceAnnotationBeanPostProcessor.java | 11 +- ...nceAnnotationWithAotBeanPostProcessor.java | 510 +----------------- ...ServiceAnnotationWithAotPostProcessor.java | 9 +- 3 files changed, 35 insertions(+), 495 deletions(-) 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 1e4d033b8d..0f43babab7 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 @@ -110,10 +110,10 @@ public class ReferenceAnnotationBeanPostProcessor extends AbstractAnnotationBean private final ConcurrentMap injectedMethodReferenceBeanCache = new ConcurrentHashMap<>(CACHE_SIZE); - private ApplicationContext applicationContext; + protected ApplicationContext applicationContext; - private ReferenceBeanManager referenceBeanManager; - private BeanDefinitionRegistry beanDefinitionRegistry; + protected ReferenceBeanManager referenceBeanManager; + protected BeanDefinitionRegistry beanDefinitionRegistry; /** * {@link com.alibaba.dubbo.config.annotation.Reference @com.alibaba.dubbo.config.annotation.Reference} has been supported since 2.7.3 @@ -211,7 +211,7 @@ public class ReferenceAnnotationBeanPostProcessor extends AbstractAnnotationBean * @param beanName * @param beanDefinition */ - private void processReferenceAnnotatedBeanDefinition(String beanName, AnnotatedBeanDefinition beanDefinition) { + protected void processReferenceAnnotatedBeanDefinition(String beanName, AnnotatedBeanDefinition beanDefinition) { MethodMetadata factoryMethodMetadata = SpringCompatUtils.getFactoryMethodMetadata(beanDefinition); @@ -500,6 +500,9 @@ public class ReferenceAnnotationBeanPostProcessor extends AbstractAnnotationBean beanDefinition.setAttribute(ReferenceAttributes.INTERFACE_CLASS, interfaceClass); beanDefinition.setAttribute(ReferenceAttributes.INTERFACE_NAME, interfaceName); + beanDefinition.getPropertyValues().add(ReferenceAttributes.INTERFACE_CLASS, interfaceClass); + beanDefinition.getPropertyValues().add(ReferenceAttributes.INTERFACE_NAME, interfaceName); + // create decorated definition for reference bean, Avoid being instantiated when getting the beanType of ReferenceBean // see org.springframework.beans.factory.support.AbstractBeanFactory#getTypeForFactoryBean() GenericBeanDefinition targetDefinition = new GenericBeanDefinition(); diff --git a/dubbo-config/dubbo-config-spring6/src/main/java/org/apache/dubbo/config/spring6/beans/factory/annotation/ReferenceAnnotationWithAotBeanPostProcessor.java b/dubbo-config/dubbo-config-spring6/src/main/java/org/apache/dubbo/config/spring6/beans/factory/annotation/ReferenceAnnotationWithAotBeanPostProcessor.java index 37d67bf2de..3104ef00c3 100644 --- a/dubbo-config/dubbo-config-spring6/src/main/java/org/apache/dubbo/config/spring6/beans/factory/annotation/ReferenceAnnotationWithAotBeanPostProcessor.java +++ b/dubbo-config/dubbo-config-spring6/src/main/java/org/apache/dubbo/config/spring6/beans/factory/annotation/ReferenceAnnotationWithAotBeanPostProcessor.java @@ -19,26 +19,17 @@ package org.apache.dubbo.config.spring6.beans.factory.annotation; import org.apache.dubbo.common.logger.ErrorTypeAwareLogger; import org.apache.dubbo.common.logger.LoggerFactory; -import org.apache.dubbo.common.utils.ArrayUtils; -import org.apache.dubbo.common.utils.Assert; import org.apache.dubbo.common.utils.ClassUtils; -import org.apache.dubbo.common.utils.StringUtils; import org.apache.dubbo.config.annotation.DubboReference; -import org.apache.dubbo.config.annotation.Reference; -import org.apache.dubbo.config.spring.Constants; import org.apache.dubbo.config.spring.ReferenceBean; -import org.apache.dubbo.config.spring.beans.factory.annotation.AbstractAnnotationBeanPostProcessor; +import org.apache.dubbo.config.spring.beans.factory.annotation.ReferenceAnnotationBeanPostProcessor; import org.apache.dubbo.config.spring.context.event.DubboConfigInitEvent; -import org.apache.dubbo.config.spring.reference.ReferenceAttributes; -import org.apache.dubbo.config.spring.reference.ReferenceBeanManager; -import org.apache.dubbo.config.spring.reference.ReferenceBeanSupport; import org.apache.dubbo.config.spring.util.SpringCompatUtils; import org.apache.dubbo.config.spring6.beans.factory.aot.ReferencedFieldValueResolver; import org.apache.dubbo.config.spring6.beans.factory.aot.ReferencedMethodArgumentsResolver; import org.apache.dubbo.config.spring6.utils.AotUtils; import org.apache.dubbo.rpc.service.Destroyable; import org.apache.dubbo.rpc.service.EchoService; -import org.apache.dubbo.rpc.service.GenericService; import org.springframework.aop.SpringProxy; import org.springframework.aop.framework.Advised; import org.springframework.aot.generate.AccessControl; @@ -51,100 +42,44 @@ import org.springframework.aot.hint.RuntimeHints; import org.springframework.aot.hint.TypeReference; import org.springframework.aot.hint.support.ClassHintUtils; import org.springframework.beans.BeansException; -import org.springframework.beans.PropertyValue; -import org.springframework.beans.PropertyValues; -import org.springframework.beans.factory.BeanCreationException; import org.springframework.beans.factory.annotation.AnnotatedBeanDefinition; -import org.springframework.beans.factory.annotation.InjectionMetadata; import org.springframework.beans.factory.aot.AutowiredArgumentsCodeGenerator; import org.springframework.beans.factory.aot.BeanRegistrationAotContribution; import org.springframework.beans.factory.aot.BeanRegistrationAotProcessor; import org.springframework.beans.factory.aot.BeanRegistrationCode; import org.springframework.beans.factory.config.BeanDefinition; -import org.springframework.beans.factory.config.BeanDefinitionHolder; -import org.springframework.beans.factory.config.BeanFactoryPostProcessor; import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; import org.springframework.beans.factory.config.DependencyDescriptor; import org.springframework.beans.factory.support.AutowireCandidateResolver; -import org.springframework.beans.factory.support.BeanDefinitionRegistry; import org.springframework.beans.factory.support.DefaultListableBeanFactory; -import org.springframework.beans.factory.support.GenericBeanDefinition; import org.springframework.beans.factory.support.RegisteredBean; import org.springframework.beans.factory.support.RootBeanDefinition; -import org.springframework.context.ApplicationContext; -import org.springframework.context.ApplicationContextAware; import org.springframework.core.DecoratingProxy; import org.springframework.core.MethodParameter; import org.springframework.core.annotation.AnnotationAttributes; -import org.springframework.core.type.MethodMetadata; import org.springframework.javapoet.ClassName; import org.springframework.javapoet.CodeBlock; import org.springframework.lang.Nullable; import org.springframework.util.CollectionUtils; -import java.beans.PropertyDescriptor; -import java.lang.annotation.Annotation; import java.lang.reflect.Field; import java.lang.reflect.Member; import java.lang.reflect.Method; import java.lang.reflect.Parameter; -import java.util.Collection; -import java.util.Collections; -import java.util.HashMap; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ConcurrentMap; -import static com.alibaba.spring.util.AnnotationUtils.getAttribute; import static org.apache.dubbo.common.constants.LoggerCodeConstants.CONFIG_DUBBO_BEAN_INITIALIZER; -import static org.apache.dubbo.common.utils.AnnotationUtils.filterDefaultValues; -import static org.springframework.util.StringUtils.hasText; /** - *

- * Step 1: - * The purpose of implementing {@link BeanFactoryPostProcessor} is to scan the registration reference bean definition earlier, - * so that it can be shared with the xml bean configuration. - *

+ * The purpose of implementing {@link BeanRegistrationAotProcessor} is to + * supplement for {@link ReferenceAnnotationBeanPostProcessor} ability of AOT. * - *

- * Step 2: - * By implementing {@link org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessor}, - * inject the reference bean instance into the fields and setter methods which annotated with {@link DubboReference}. - *

- * - * @see DubboReference - * @see Reference - * @see com.alibaba.dubbo.config.annotation.Reference - * @since 2.5.7 + * @since 3.3 */ -public class ReferenceAnnotationWithAotBeanPostProcessor extends AbstractAnnotationBeanPostProcessor - implements ApplicationContextAware, BeanRegistrationAotProcessor, BeanFactoryPostProcessor { - - /** - * The bean name of {@link ReferenceAnnotationWithAotBeanPostProcessor} - */ - public static final String BEAN_NAME = ReferenceAnnotationWithAotBeanPostProcessor.class.getName(); - - /** - * Cache size - */ - private static final int CACHE_SIZE = Integer.getInteger(BEAN_NAME + ".cache.size", 32); +public class ReferenceAnnotationWithAotBeanPostProcessor extends ReferenceAnnotationBeanPostProcessor + implements BeanRegistrationAotProcessor { private final ErrorTypeAwareLogger logger = LoggerFactory.getErrorTypeAwareLogger(getClass()); - private final ConcurrentMap injectedFieldReferenceBeanCache = - new ConcurrentHashMap<>(CACHE_SIZE); - - private final ConcurrentMap injectedMethodReferenceBeanCache = - new ConcurrentHashMap<>(CACHE_SIZE); - - private ApplicationContext applicationContext; - - private ReferenceBeanManager referenceBeanManager; - private BeanDefinitionRegistry beanDefinitionRegistry; @Nullable private ConfigurableListableBeanFactory beanFactory; @@ -155,7 +90,7 @@ public class ReferenceAnnotationWithAotBeanPostProcessor extends AbstractAnnotat * {@link DubboReference @DubboReference} has been supported since 2.7.7 */ public ReferenceAnnotationWithAotBeanPostProcessor() { - super(DubboReference.class, Reference.class, com.alibaba.dubbo.config.annotation.Reference.class); + super(); } @Override @@ -192,18 +127,6 @@ public class ReferenceAnnotationWithAotBeanPostProcessor extends AbstractAnnotat } } -// if (beanFactory instanceof AbstractBeanFactory) { -// List beanPostProcessors = ((AbstractBeanFactory) beanFactory).getBeanPostProcessors(); -// for (BeanPostProcessor beanPostProcessor : beanPostProcessors) { -// if (beanPostProcessor == this) { -// // This bean has been registered as BeanPostProcessor at org.apache.dubbo.config.spring.context.DubboInfraBeanRegisterPostProcessor.postProcessBeanFactory() -// // so destroy this bean here, prevent register it as BeanPostProcessor again, avoid cause BeanPostProcessorChecker detection error -// beanDefinitionRegistry.removeBeanDefinition(BEAN_NAME); -// break; -// } -// } -// } - try { // this is an early event, it will be notified at org.springframework.context.support.AbstractApplicationContext.registerListeners() applicationContext.publishEvent(new DubboConfigInitEvent(applicationContext)); @@ -227,157 +150,6 @@ public class ReferenceAnnotationWithAotBeanPostProcessor extends AbstractAnnotat return false; } - /** - * process @DubboReference at java-config @bean method - *
-     * @Configuration
-     * public class ConsumerConfig {
-     *
-     *      @Bean
-     *      @DubboReference(group="demo", version="1.2.3")
-     *      public ReferenceBean<DemoService> demoService() {
-     *          return new ReferenceBean();
-     *      }
-     *
-     * }
-     * 
- * - * @param beanName - * @param beanDefinition - */ - private void processReferenceAnnotatedBeanDefinition(String beanName, AnnotatedBeanDefinition beanDefinition) { - - MethodMetadata factoryMethodMetadata = SpringCompatUtils.getFactoryMethodMetadata(beanDefinition); - - // Extract beanClass from generic return type of java-config bean method: ReferenceBean - // see org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.getTypeForFactoryBeanFromMethod - Class beanClass = getBeanFactory().getType(beanName); - if (beanClass == Object.class) { - beanClass = SpringCompatUtils.getGenericTypeOfReturnType(factoryMethodMetadata); - } - if (beanClass == Object.class) { - // bean class is invalid, ignore it - return; - } - - if (beanClass == null) { - String beanMethodSignature = factoryMethodMetadata.getDeclaringClassName() + "#" + factoryMethodMetadata.getMethodName() + "()"; - throw new BeanCreationException("The ReferenceBean is missing necessary generic type, which returned by the @Bean method of Java-config class. " + - "The generic type of the returned ReferenceBean must be specified as the referenced interface type, " + - "such as ReferenceBean. Please check bean method: " + beanMethodSignature); - } - - // get dubbo reference annotation attributes - Map annotationAttributes = null; - // try all dubbo reference annotation types - for (Class annotationType : getAnnotationTypes()) { - if (factoryMethodMetadata.isAnnotated(annotationType.getName())) { - // Since Spring 5.2 - // return factoryMethodMetadata.getAnnotations().get(annotationType).filterDefaultValues().asMap(); - // Compatible with Spring 4.x - annotationAttributes = factoryMethodMetadata.getAnnotationAttributes(annotationType.getName()); - annotationAttributes = filterDefaultValues(annotationType, annotationAttributes); - break; - } - } - - if (annotationAttributes != null) { - // @DubboReference on @Bean method - LinkedHashMap attributes = new LinkedHashMap<>(annotationAttributes); - // reset id attribute - attributes.put(ReferenceAttributes.ID, beanName); - // convert annotation props - ReferenceBeanSupport.convertReferenceProps(attributes, beanClass); - - // get interface - String interfaceName = (String) attributes.get(ReferenceAttributes.INTERFACE); - - // check beanClass and reference interface class - if (!StringUtils.isEquals(interfaceName, beanClass.getName()) && beanClass != GenericService.class) { - String beanMethodSignature = factoryMethodMetadata.getDeclaringClassName() + "#" + factoryMethodMetadata.getMethodName() + "()"; - throw new BeanCreationException("The 'interfaceClass' or 'interfaceName' attribute value of @DubboReference annotation " + - "is inconsistent with the generic type of the ReferenceBean returned by the bean method. " + - "The interface class of @DubboReference is: " + interfaceName + ", but return ReferenceBean<" + beanClass.getName() + ">. " + - "Please remove the 'interfaceClass' and 'interfaceName' attributes from @DubboReference annotation. " + - "Please check bean method: " + beanMethodSignature); - } - - Class interfaceClass = beanClass; - - // set attribute instead of property values - beanDefinition.setAttribute(Constants.REFERENCE_PROPS, attributes); - beanDefinition.setAttribute(ReferenceAttributes.INTERFACE_CLASS, interfaceClass); - beanDefinition.setAttribute(ReferenceAttributes.INTERFACE_NAME, interfaceName); - } else { - // raw reference bean - // the ReferenceBean is not yet initialized - beanDefinition.setAttribute(ReferenceAttributes.INTERFACE_CLASS, beanClass); - if (beanClass != GenericService.class) { - beanDefinition.setAttribute(ReferenceAttributes.INTERFACE_NAME, beanClass.getName()); - } - } - - // set id - beanDefinition.getPropertyValues().add(ReferenceAttributes.ID, beanName); - } - - @Override - public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class beanType, String beanName) { - if (beanType != null) { - if (isReferenceBean(beanDefinition)) { - //mark property value as optional - List propertyValues = beanDefinition.getPropertyValues().getPropertyValueList(); - for (PropertyValue propertyValue : propertyValues) { - propertyValue.setOptional(true); - } - } else if (isAnnotatedReferenceBean(beanDefinition)) { - // extract beanClass from java-config bean method generic return type: ReferenceBean - //Class beanClass = getBeanFactory().getType(beanName); - } else { - AnnotatedInjectionMetadata metadata = findInjectionMetadata(beanName, beanType, null); - metadata.checkConfigMembers(beanDefinition); - try { - prepareInjection(metadata); - } catch (Exception e) { - throw new IllegalStateException("Prepare dubbo reference injection element failed", e); - } - } - } - } - - /** - * Alternatives to the {@link #postProcessProperties(PropertyValues, Object, String)}, that removed as of Spring - * Framework 6.0.0, and in favor of {@link #postProcessProperties(PropertyValues, Object, String)}. - *

In order to be compatible with the lower version of Spring, it is still retained. - * - * @see #postProcessProperties - */ - public PropertyValues postProcessPropertyValues( - PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeansException { - return postProcessProperties(pvs, bean, beanName); - } - - /** - * Alternatives to the {@link #postProcessPropertyValues(PropertyValues, PropertyDescriptor[], Object, String)}. - * - * @see #postProcessPropertyValues - */ - @Override - public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) - throws BeansException { - try { - AnnotatedInjectionMetadata metadata = findInjectionMetadata(beanName, bean.getClass(), pvs); - prepareInjection(metadata); - metadata.inject(bean, beanName, pvs); - } catch (BeansException ex) { - throw ex; - } catch (Throwable ex) { - throw new BeanCreationException(beanName, "Injection of @" + getAnnotationType().getSimpleName() - + " dependencies is failed", ex); - } - return pvs; - } - private boolean isReferenceBean(BeanDefinition beanDefinition) { return ReferenceBean.class.getName().equals(beanDefinition.getBeanClassName()); } @@ -401,238 +173,6 @@ public class ReferenceAnnotationWithAotBeanPostProcessor extends AbstractAnnotat return metadata; } - protected void prepareInjection(AnnotatedInjectionMetadata metadata) throws BeansException { - try { - //find and register bean definition for @DubboReference/@Reference - for (AnnotatedFieldElement fieldElement : metadata.getFieldElements()) { - if (fieldElement.injectedObject != null) { - continue; - } - Class injectedType = fieldElement.field.getType(); - AnnotationAttributes attributes = fieldElement.attributes; - String referenceBeanName = registerReferenceBean(fieldElement.getPropertyName(), injectedType, attributes, fieldElement.field); - - //associate fieldElement and reference bean - fieldElement.injectedObject = referenceBeanName; - injectedFieldReferenceBeanCache.put(fieldElement, referenceBeanName); - - } - - for (AnnotatedMethodElement methodElement : metadata.getMethodElements()) { - if (methodElement.injectedObject != null) { - continue; - } - Class injectedType = methodElement.getInjectedType(); - AnnotationAttributes attributes = methodElement.attributes; - String referenceBeanName = registerReferenceBean(methodElement.getPropertyName(), injectedType, attributes, methodElement.method); - - //associate methodElement and reference bean - methodElement.injectedObject = referenceBeanName; - injectedMethodReferenceBeanCache.put(methodElement, referenceBeanName); - } - } catch (ClassNotFoundException e) { - throw new BeanCreationException("prepare reference annotation failed", e); - } - } - - public String registerReferenceBean(String propertyName, Class injectedType, Map attributes, Member member) throws BeansException { - - boolean renameable = true; - // referenceBeanName - String referenceBeanName = getAttribute(attributes, ReferenceAttributes.ID); - if (hasText(referenceBeanName)) { - renameable = false; - } else { - referenceBeanName = propertyName; - } - - String checkLocation = "Please check " + member.toString(); - - // convert annotation props - ReferenceBeanSupport.convertReferenceProps(attributes, injectedType); - - // get interface - String interfaceName = (String) attributes.get(ReferenceAttributes.INTERFACE); - if (StringUtils.isBlank(interfaceName)) { - throw new BeanCreationException("Need to specify the 'interfaceName' or 'interfaceClass' attribute of '@DubboReference' if enable generic. " + checkLocation); - } - - // check reference key - String referenceKey = ReferenceBeanSupport.generateReferenceKey(attributes, applicationContext); - - // find reference bean name by reference key - List registeredReferenceBeanNames = referenceBeanManager.getBeanNamesByKey(referenceKey); - if (registeredReferenceBeanNames.size() > 0) { - // found same name and reference key - if (registeredReferenceBeanNames.contains(referenceBeanName)) { - return referenceBeanName; - } - } - - //check bean definition - boolean isContains; - if ((isContains = beanDefinitionRegistry.containsBeanDefinition(referenceBeanName)) || beanDefinitionRegistry.isAlias(referenceBeanName)) { - String preReferenceBeanName = referenceBeanName; - if (!isContains) { - // Look in the alias for the origin bean name - String[] aliases = beanDefinitionRegistry.getAliases(referenceBeanName); - if (ArrayUtils.isNotEmpty(aliases)) { - for (String alias : aliases) { - if (beanDefinitionRegistry.containsBeanDefinition(alias)) { - preReferenceBeanName = alias; - break; - } - } - } - } - BeanDefinition prevBeanDefinition = beanDefinitionRegistry.getBeanDefinition(preReferenceBeanName); - String prevBeanType = prevBeanDefinition.getBeanClassName(); - String prevBeanDesc = referenceBeanName + "[" + prevBeanType + "]"; - String newBeanDesc = referenceBeanName + "[" + referenceKey + "]"; - - if (isReferenceBean(prevBeanDefinition)) { - //check reference key - String prevReferenceKey = ReferenceBeanSupport.generateReferenceKey(prevBeanDefinition, applicationContext); - if (StringUtils.isEquals(prevReferenceKey, referenceKey)) { - //found matched dubbo reference bean, ignore register - return referenceBeanName; - } - //get interfaceName from attribute - Assert.notNull(prevBeanDefinition, "The interface class of ReferenceBean is not initialized"); - prevBeanDesc = referenceBeanName + "[" + prevReferenceKey + "]"; - } - - // bean name from attribute 'id' or java-config bean, cannot be renamed - if (!renameable) { - throw new BeanCreationException("Already exists another bean definition with the same bean name [" + referenceBeanName + "], " + - "but cannot rename the reference bean name (specify the id attribute or java-config bean), " + - "please modify the name of one of the beans: " + - "prev: " + prevBeanDesc + ", new: " + newBeanDesc + ". " + checkLocation); - } - - // the prev bean type is different, rename the new reference bean - int index = 2; - String newReferenceBeanName = null; - while (newReferenceBeanName == null || beanDefinitionRegistry.containsBeanDefinition(newReferenceBeanName) - || beanDefinitionRegistry.isAlias(newReferenceBeanName)) { - newReferenceBeanName = referenceBeanName + "#" + index; - index++; - // double check found same name and reference key - if (registeredReferenceBeanNames.contains(newReferenceBeanName)) { - return newReferenceBeanName; - } - } - newBeanDesc = newReferenceBeanName + "[" + referenceKey + "]"; - - logger.warn(CONFIG_DUBBO_BEAN_INITIALIZER, "", "", "Already exists another bean definition with the same bean name [" + referenceBeanName + "], " + - "rename dubbo reference bean to [" + newReferenceBeanName + "]. " + - "It is recommended to modify the name of one of the beans to avoid injection problems. " + - "prev: " + prevBeanDesc + ", new: " + newBeanDesc + ". " + checkLocation); - referenceBeanName = newReferenceBeanName; - } - attributes.put(ReferenceAttributes.ID, referenceBeanName); - - // If registered matched reference before, just register alias - if (registeredReferenceBeanNames.size() > 0) { - beanDefinitionRegistry.registerAlias(registeredReferenceBeanNames.get(0), referenceBeanName); - referenceBeanManager.registerReferenceKeyAndBeanName(referenceKey, referenceBeanName); - return referenceBeanName; - } - - Class interfaceClass = injectedType; - - // TODO Only register one reference bean for same (group, interface, version) - - // Register the reference bean definition to the beanFactory - RootBeanDefinition beanDefinition = new RootBeanDefinition(); - beanDefinition.setBeanClassName(ReferenceBean.class.getName()); - beanDefinition.getPropertyValues().add(ReferenceAttributes.ID, referenceBeanName); - - // set attribute instead of property values - beanDefinition.setAttribute(Constants.REFERENCE_PROPS, attributes); - beanDefinition.setAttribute(ReferenceAttributes.INTERFACE_CLASS, interfaceClass); - beanDefinition.setAttribute(ReferenceAttributes.INTERFACE_NAME, interfaceName); -// beanDefinition.getPropertyValues().add(Constants.REFERENCE_PROPS,attributes); - beanDefinition.getPropertyValues().add(ReferenceAttributes.INTERFACE_CLASS, interfaceClass); - beanDefinition.getPropertyValues().add(ReferenceAttributes.INTERFACE_NAME, interfaceName); - // create decorated definition for reference bean, Avoid being instantiated when getting the beanType of ReferenceBean - // see org.springframework.beans.factory.support.AbstractBeanFactory#getTypeForFactoryBean() - GenericBeanDefinition targetDefinition = new GenericBeanDefinition(); - targetDefinition.setBeanClass(interfaceClass); - beanDefinition.setDecoratedDefinition(new BeanDefinitionHolder(targetDefinition, referenceBeanName + "_decorated")); - - // signal object type since Spring 5.2 - beanDefinition.setAttribute(Constants.OBJECT_TYPE_ATTRIBUTE, interfaceClass); - - beanDefinitionRegistry.registerBeanDefinition(referenceBeanName, beanDefinition); - referenceBeanManager.registerReferenceKeyAndBeanName(referenceKey, referenceBeanName); - logger.info("Register dubbo reference bean: " + referenceBeanName + " = " + referenceKey + " at " + member); - return referenceBeanName; - } - - @Override - protected Object doGetInjectedBean(AnnotationAttributes attributes, Object bean, String beanName, Class injectedType, - AnnotatedInjectElement injectedElement) throws Exception { - - if (injectedElement.injectedObject == null) { - throw new IllegalStateException("The AnnotatedInjectElement of @DubboReference should be inited before injection"); - } - - return getBeanFactory().getBean((String) injectedElement.injectedObject); - } - - @Override - public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { - this.applicationContext = applicationContext; - this.referenceBeanManager = applicationContext.getBean(ReferenceBeanManager.BEAN_NAME, ReferenceBeanManager.class); - this.beanDefinitionRegistry = (BeanDefinitionRegistry) applicationContext.getAutowireCapableBeanFactory(); - } - - @Override - public void destroy() throws Exception { - super.destroy(); - this.injectedFieldReferenceBeanCache.clear(); - this.injectedMethodReferenceBeanCache.clear(); - } - - /** - * Gets all beans of {@link ReferenceBean} - * - * @deprecated use {@link ReferenceBeanManager#getReferences()} instead - */ - @Deprecated - public Collection> getReferenceBeans() { - return Collections.emptyList(); - } - - /** - * Get {@link ReferenceBean} {@link Map} in injected field. - * - * @return non-null {@link Map} - * @since 2.5.11 - */ - public Map> getInjectedFieldReferenceBeanMap() { - Map> map = new HashMap<>(); - for (Map.Entry entry : injectedFieldReferenceBeanCache.entrySet()) { - map.put(entry.getKey(), referenceBeanManager.getById(entry.getValue())); - } - return Collections.unmodifiableMap(map); - } - - /** - * Get {@link ReferenceBean} {@link Map} in injected method. - * - * @return non-null {@link Map} - * @since 2.5.11 - */ - public Map> getInjectedMethodReferenceBeanMap() { - Map> map = new HashMap<>(); - for (Map.Entry entry : injectedMethodReferenceBeanCache.entrySet()) { - map.put(entry.getKey(), referenceBeanManager.getById(entry.getValue())); - } - return Collections.unmodifiableMap(map); - } - @Nullable private AutowireCandidateResolver getAutowireCandidateResolver() { if (this.beanFactory instanceof DefaultListableBeanFactory) { @@ -665,19 +205,19 @@ public class ReferenceAnnotationWithAotBeanPostProcessor extends AbstractAnnotat @Override public void applyTo(GenerationContext generationContext, BeanRegistrationCode beanRegistrationCode) { GeneratedClass generatedClass = generationContext.getGeneratedClasses() - .addForFeatureComponent("DubboReference", this.target, type -> { - type.addJavadoc("DubboReference for {@link $T}.", this.target); - type.addModifiers(javax.lang.model.element.Modifier.PUBLIC); - }); + .addForFeatureComponent("DubboReference", this.target, type -> { + type.addJavadoc("DubboReference for {@link $T}.", this.target); + type.addModifiers(javax.lang.model.element.Modifier.PUBLIC); + }); GeneratedMethod generateMethod = generatedClass.getMethods().add("apply", method -> { method.addJavadoc("Apply the dubbo reference."); method.addModifiers(javax.lang.model.element.Modifier.PUBLIC, - javax.lang.model.element.Modifier.STATIC); + javax.lang.model.element.Modifier.STATIC); method.addParameter(RegisteredBean.class, REGISTERED_BEAN_PARAMETER); method.addParameter(this.target, INSTANCE_PARAMETER); method.returns(this.target); method.addCode(generateMethodCode(generatedClass.getName(), - generationContext.getRuntimeHints())); + generationContext.getRuntimeHints())); }); beanRegistrationCode.addInstancePostProcessor(generateMethod.toMethodReference()); @@ -691,13 +231,13 @@ public class ReferenceAnnotationWithAotBeanPostProcessor extends AbstractAnnotat if (!CollectionUtils.isEmpty(this.annotatedInjectionMetadata.getFieldElements())) { for (AnnotatedInjectElement referenceElement : this.annotatedInjectionMetadata.getFieldElements()) { code.addStatement(generateMethodStatementForElement( - targetClassName, referenceElement, hints)); + targetClassName, referenceElement, hints)); } } if (!CollectionUtils.isEmpty(this.annotatedInjectionMetadata.getMethodElements())) { for (AnnotatedInjectElement referenceElement : this.annotatedInjectionMetadata.getMethodElements()) { code.addStatement(generateMethodStatementForElement( - targetClassName, referenceElement, hints)); + targetClassName, referenceElement, hints)); } } code.addStatement("return $L", INSTANCE_PARAMETER); @@ -723,14 +263,14 @@ public class ReferenceAnnotationWithAotBeanPostProcessor extends AbstractAnnotat if (member instanceof Field) { return generateMethodStatementForField( - targetClassName, (Field) member, attributes, injectedObject, hints); + targetClassName, (Field) member, attributes, injectedObject, hints); } if (member instanceof Method) { return generateMethodStatementForMethod( - targetClassName, (Method) member, attributes, injectedObject, hints); + targetClassName, (Method) member, attributes, injectedObject, hints); } throw new IllegalStateException( - "Unsupported member type " + member.getClass().getName()); + "Unsupported member type " + member.getClass().getName()); } private CodeBlock generateMethodStatementForField(ClassName targetClassName, @@ -738,17 +278,17 @@ public class ReferenceAnnotationWithAotBeanPostProcessor extends AbstractAnnotat hints.reflection().registerField(field); CodeBlock resolver = CodeBlock.of("$T.$L($S)", - ReferencedFieldValueResolver.class, - "forRequiredField", field.getName()); + ReferencedFieldValueResolver.class, + "forRequiredField", field.getName()); CodeBlock shortcutResolver = CodeBlock.of("$L.withShortcut($S)", resolver, injectedObject); AccessControl accessControl = AccessControl.forMember(field); if (!accessControl.isAccessibleFrom(targetClassName)) { return CodeBlock.of("$L.resolveAndSet($L, $L)", shortcutResolver, - REGISTERED_BEAN_PARAMETER, INSTANCE_PARAMETER); + REGISTERED_BEAN_PARAMETER, INSTANCE_PARAMETER); } return CodeBlock.of("$L.$L = $L.resolve($L)", INSTANCE_PARAMETER, - field.getName(), shortcutResolver, REGISTERED_BEAN_PARAMETER); + field.getName(), shortcutResolver, REGISTERED_BEAN_PARAMETER); } private CodeBlock generateMethodStatementForMethod(ClassName targetClassName, @@ -776,9 +316,9 @@ public class ReferenceAnnotationWithAotBeanPostProcessor extends AbstractAnnotat } else { hints.reflection().registerMethod(method, ExecutableMode.INTROSPECT); CodeBlock arguments = new AutowiredArgumentsCodeGenerator(this.target, - method).generateCode(method.getParameterTypes()); + method).generateCode(method.getParameterTypes()); CodeBlock injectionCode = CodeBlock.of("args -> $L.$L($L)", - INSTANCE_PARAMETER, method.getName(), arguments); + INSTANCE_PARAMETER, method.getName(), arguments); code.add(".resolve($L, $L)", REGISTERED_BEAN_PARAMETER, injectionCode); } return code.build(); @@ -832,7 +372,7 @@ public class ReferenceAnnotationWithAotBeanPostProcessor extends AbstractAnnotat private void registerProxyIfNecessary(RuntimeHints runtimeHints, DependencyDescriptor dependencyDescriptor) { if (this.candidateResolver != null) { Class proxyClass = - this.candidateResolver.getLazyResolutionProxyClass(dependencyDescriptor, null); + this.candidateResolver.getLazyResolutionProxyClass(dependencyDescriptor, null); if (proxyClass != null) { ClassHintUtils.registerProxyIfNecessary(proxyClass, runtimeHints); } diff --git a/dubbo-config/dubbo-config-spring6/src/main/java/org/apache/dubbo/config/spring6/beans/factory/annotation/ServiceAnnotationWithAotPostProcessor.java b/dubbo-config/dubbo-config-spring6/src/main/java/org/apache/dubbo/config/spring6/beans/factory/annotation/ServiceAnnotationWithAotPostProcessor.java index 03210dc72d..738b1b940a 100644 --- a/dubbo-config/dubbo-config-spring6/src/main/java/org/apache/dubbo/config/spring6/beans/factory/annotation/ServiceAnnotationWithAotPostProcessor.java +++ b/dubbo-config/dubbo-config-spring6/src/main/java/org/apache/dubbo/config/spring6/beans/factory/annotation/ServiceAnnotationWithAotPostProcessor.java @@ -18,7 +18,6 @@ package org.apache.dubbo.config.spring6.beans.factory.annotation; import org.apache.dubbo.common.logger.ErrorTypeAwareLogger; import org.apache.dubbo.common.logger.LoggerFactory; -import org.apache.dubbo.config.annotation.Service; import org.apache.dubbo.config.spring.ServiceBean; import org.apache.dubbo.config.spring.beans.factory.annotation.ServiceAnnotationPostProcessor; import org.apache.dubbo.config.spring.schema.AnnotationBeanDefinitionParser; @@ -29,21 +28,19 @@ import org.springframework.aot.hint.TypeReference; import org.springframework.beans.factory.aot.BeanRegistrationAotContribution; import org.springframework.beans.factory.aot.BeanRegistrationAotProcessor; import org.springframework.beans.factory.aot.BeanRegistrationCode; -import org.springframework.beans.factory.config.BeanFactoryPostProcessor; import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor; import org.springframework.beans.factory.support.RegisteredBean; import org.springframework.beans.factory.support.RootBeanDefinition; -import org.springframework.beans.factory.xml.BeanDefinitionParser; import java.util.Collection; /** - * A {@link BeanFactoryPostProcessor} used for processing of {@link Service @Service} annotated classes and annotated bean in java config classes. - * It's also the infrastructure class of XML {@link BeanDefinitionParser} on <dubbo:annotation /> + * The purpose of implementing {@link BeanRegistrationAotProcessor} is to + * supplement for {@link ServiceAnnotationPostProcessor} ability of AOT. * * @see AnnotationBeanDefinitionParser * @see BeanDefinitionRegistryPostProcessor - * @since 3.2 + * @since 3.3 */ public class ServiceAnnotationWithAotPostProcessor extends ServiceAnnotationPostProcessor implements BeanRegistrationAotProcessor {