diff --git a/spring-beans/src/main/java/org/springframework/beans/factory/annotation/AutowiredAnnotationBeanPostProcessor.java b/spring-beans/src/main/java/org/springframework/beans/factory/annotation/AutowiredAnnotationBeanPostProcessor.java index 94a80f3b59e6..9c7686d51cdb 100644 --- a/spring-beans/src/main/java/org/springframework/beans/factory/annotation/AutowiredAnnotationBeanPostProcessor.java +++ b/spring-beans/src/main/java/org/springframework/beans/factory/annotation/AutowiredAnnotationBeanPostProcessor.java @@ -159,6 +159,9 @@ public class AutowiredAnnotationBeanPostProcessor implements SmartInstantiationAwareBeanPostProcessor, MergedBeanDefinitionPostProcessor, BeanRegistrationAotProcessor, PriorityOrdered, BeanFactoryAware { + private static final Constructor[] EMPTY_CONSTRUCTOR_ARRAY = new Constructor[0]; + + protected final Log logger = LogFactory.getLog(getClass()); private final Set> autowiredAnnotationTypes = new LinkedHashSet<>(4); @@ -286,7 +289,25 @@ public void setBeanFactory(BeanFactory beanFactory) { @Override public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class beanType, String beanName) { + // Register externally managed config members on bean definition. findInjectionMetadata(beanName, beanType, beanDefinition); + + // Use opportunity to clear caches which are not needed after singleton instantiation. + // The injectionMetadataCache itself is left intact since it cannot be reliably + // reconstructed in terms of externally managed config members otherwise. + if (beanDefinition.isSingleton()) { + this.candidateConstructorsCache.remove(beanType); + // With actual lookup overrides, keep it intact along with bean definition. + if (!beanDefinition.hasMethodOverrides()) { + this.lookupMethodsChecked.remove(beanName); + } + } + } + + @Override + public void resetBeanDefinition(String beanName) { + this.lookupMethodsChecked.remove(beanName); + this.injectionMetadataCache.remove(beanName); } @Override @@ -324,12 +345,6 @@ private InjectionMetadata findInjectionMetadata(String beanName, Class beanTy return metadata; } - @Override - public void resetBeanDefinition(String beanName) { - this.lookupMethodsChecked.remove(beanName); - this.injectionMetadataCache.remove(beanName); - } - @Override public Class determineBeanType(Class beanClass, String beanName) throws BeanCreationException { checkLookupMethods(beanClass, beanName); @@ -429,7 +444,7 @@ else if (candidates.size() == 1 && logger.isInfoEnabled()) { "default constructor to fall back to: " + candidates.get(0)); } } - candidateConstructors = candidates.toArray(new Constructor[0]); + candidateConstructors = candidates.toArray(EMPTY_CONSTRUCTOR_ARRAY); } else if (rawCandidates.length == 1 && rawCandidates[0].getParameterCount() > 0) { candidateConstructors = new Constructor[] {rawCandidates[0]}; @@ -442,7 +457,7 @@ else if (nonSyntheticConstructors == 1 && primaryConstructor != null) { candidateConstructors = new Constructor[] {primaryConstructor}; } else { - candidateConstructors = new Constructor[0]; + candidateConstructors = EMPTY_CONSTRUCTOR_ARRAY; } this.candidateConstructorsCache.put(beanClass, candidateConstructors); }