diff --git a/spring-context/src/main/java/org/springframework/context/support/PostProcessorRegistrationDelegate.java b/spring-context/src/main/java/org/springframework/context/support/PostProcessorRegistrationDelegate.java index 849c6a9e9ceb..85b2e9407c99 100644 --- a/spring-context/src/main/java/org/springframework/context/support/PostProcessorRegistrationDelegate.java +++ b/spring-context/src/main/java/org/springframework/context/support/PostProcessorRegistrationDelegate.java @@ -16,6 +16,7 @@ package org.springframework.context.support; +import java.lang.reflect.Field; import java.util.ArrayList; import java.util.Collection; import java.util.Comparator; @@ -47,6 +48,7 @@ import org.springframework.core.metrics.ApplicationStartup; import org.springframework.core.metrics.StartupStep; import org.springframework.lang.Nullable; +import org.springframework.util.ReflectionUtils; /** * Delegate for AbstractApplicationContext's post-processor handling. @@ -315,6 +317,7 @@ static List loadBeanPostProcessors( */ static void invokeMergedBeanDefinitionPostProcessors(DefaultListableBeanFactory beanFactory) { new MergedBeanDefinitionPostProcessorInvoker(beanFactory).invokeMergedBeanDefinitionPostProcessors(); + } private static void sortPostProcessors(List postProcessors, ConfigurableListableBeanFactory beanFactory) { @@ -364,7 +367,7 @@ private static void invokeBeanFactoryPostProcessors( * Register the given BeanPostProcessor beans. */ private static void registerBeanPostProcessors( - ConfigurableListableBeanFactory beanFactory, List postProcessors) { + ConfigurableListableBeanFactory beanFactory, List postProcessors) { if (beanFactory instanceof AbstractBeanFactory) { // Bulk addition is more efficient against our CopyOnWriteArrayList there @@ -439,12 +442,19 @@ private void invokeMergedBeanDefinitionPostProcessors() { Class beanType = resolveBeanType(bd); postProcessRootBeanDefinition(postProcessors, beanName, beanType, bd); } + registerBeanPostProcessors(this.beanFactory, postProcessors); } private void postProcessRootBeanDefinition(List postProcessors, String beanName, Class beanType, RootBeanDefinition bd) { BeanDefinitionValueResolver valueResolver = new BeanDefinitionValueResolver(this.beanFactory, beanName, bd); - postProcessors.forEach(postProcessor -> postProcessor.postProcessMergedBeanDefinition(bd, beanType, beanName)); + postProcessors.forEach(postProcessor -> { + postProcessor.postProcessMergedBeanDefinition(bd, beanType, beanName); + // FIXME: logic should move elsewhere to access package private flag + Field postProcessed = ReflectionUtils.findField(bd.getClass(), "postProcessed"); + ReflectionUtils.makeAccessible(postProcessed); + ReflectionUtils.setField(postProcessed, bd, true); + }); for (PropertyValue propertyValue : bd.getPropertyValues().getPropertyValueList()) { Object value = propertyValue.getValue(); if (value instanceof AbstractBeanDefinition innerBd) { diff --git a/spring-context/src/test/java/org/springframework/context/annotation/AnnotationConfigApplicationContextTests.java b/spring-context/src/test/java/org/springframework/context/annotation/AnnotationConfigApplicationContextTests.java index adc78801766a..57831c404d71 100644 --- a/spring-context/src/test/java/org/springframework/context/annotation/AnnotationConfigApplicationContextTests.java +++ b/spring-context/src/test/java/org/springframework/context/annotation/AnnotationConfigApplicationContextTests.java @@ -431,6 +431,24 @@ void refreshForAotProcessingWithConfiguration() { "annotationConfigApplicationContextTests.Config", "testBean"); } + @Test + void refreshForAotCanInstantiateBeanWithAutowiredApplicationContext() { + AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(); + context.register(BeanD.class); + context.refreshForAotProcessing(); + BeanD bean = context.getBean(BeanD.class); + assertThat(bean.applicationContext).isSameAs(context); + } + + @Test + void refreshForAotCanInstantiateBeanWithFieldAutowiredApplicationContext() { + AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(); + context.register(BeanB.class); + context.refreshForAotProcessing(); + BeanB bean = context.getBean(BeanB.class); + assertThat(bean.applicationContext).isSameAs(context); + } + @Configuration static class Config { @@ -506,6 +524,16 @@ public BeanB() { static class BeanC {} + static class BeanD { + + private final ApplicationContext applicationContext; + + public BeanD(ApplicationContext applicationContext) { + this.applicationContext = applicationContext; + } + + } + static class NonInstantiatedFactoryBean implements FactoryBean { NonInstantiatedFactoryBean() {