Allow MergedBeanDefinitionPostProcessor to handle bean creation
This commit registers the MergedBeanDefinitionPostProcessor instances on the BeanFactory processed for AOT purposes. This allows beans that are created at build-time to be post-processed for low-level needs such as initialization and autowiring. Closes gh-28777
This commit is contained in:
parent
9573fc96ec
commit
ebe3b37298
|
|
@ -364,7 +364,7 @@ final class PostProcessorRegistrationDelegate {
|
|||
* Register the given BeanPostProcessor beans.
|
||||
*/
|
||||
private static void registerBeanPostProcessors(
|
||||
ConfigurableListableBeanFactory beanFactory, List<BeanPostProcessor> postProcessors) {
|
||||
ConfigurableListableBeanFactory beanFactory, List<? extends BeanPostProcessor> postProcessors) {
|
||||
|
||||
if (beanFactory instanceof AbstractBeanFactory) {
|
||||
// Bulk addition is more efficient against our CopyOnWriteArrayList there
|
||||
|
|
@ -439,6 +439,7 @@ final class PostProcessorRegistrationDelegate {
|
|||
Class<?> beanType = resolveBeanType(bd);
|
||||
postProcessRootBeanDefinition(postProcessors, beanName, beanType, bd);
|
||||
}
|
||||
registerBeanPostProcessors(this.beanFactory, postProcessors);
|
||||
}
|
||||
|
||||
private void postProcessRootBeanDefinition(List<MergedBeanDefinitionPostProcessor> postProcessors,
|
||||
|
|
|
|||
|
|
@ -431,6 +431,24 @@ class AnnotationConfigApplicationContextTests {
|
|||
"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 @@ class AnnotationConfigApplicationContextTests {
|
|||
|
||||
static class BeanC {}
|
||||
|
||||
static class BeanD {
|
||||
|
||||
private final ApplicationContext applicationContext;
|
||||
|
||||
public BeanD(ApplicationContext applicationContext) {
|
||||
this.applicationContext = applicationContext;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static class NonInstantiatedFactoryBean implements FactoryBean<String> {
|
||||
|
||||
NonInstantiatedFactoryBean() {
|
||||
|
|
|
|||
|
|
@ -23,10 +23,12 @@ import org.junit.jupiter.api.Test;
|
|||
import org.junit.jupiter.api.condition.OS;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.beans.factory.NoUniqueBeanDefinitionException;
|
||||
import org.springframework.beans.factory.config.AbstractFactoryBean;
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
|
||||
import org.springframework.beans.factory.support.AbstractBeanDefinition;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
|
||||
import org.springframework.beans.factory.support.GenericBeanDefinition;
|
||||
import org.springframework.beans.factory.support.MergedBeanDefinitionPostProcessor;
|
||||
|
|
@ -407,6 +409,32 @@ class GenericApplicationContextTests {
|
|||
context.close();
|
||||
}
|
||||
|
||||
@Test
|
||||
void refreshForAotInvokesBeanPostProcessorContractOnMergedBeanDefinitionPostProcessors() {
|
||||
MergedBeanDefinitionPostProcessor bpp = new MergedBeanDefinitionPostProcessor() {
|
||||
@Override
|
||||
public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {
|
||||
beanDefinition.setAttribute("mbdppCalled", true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
|
||||
return (beanName.equals("test") ? "42" : bean);
|
||||
}
|
||||
};
|
||||
GenericApplicationContext context = new GenericApplicationContext();
|
||||
context.registerBeanDefinition("bpp", BeanDefinitionBuilder.rootBeanDefinition(
|
||||
MergedBeanDefinitionPostProcessor.class, () -> bpp)
|
||||
.setRole(BeanDefinition.ROLE_INFRASTRUCTURE).getBeanDefinition());
|
||||
AbstractBeanDefinition bd = BeanDefinitionBuilder.rootBeanDefinition(String.class)
|
||||
.addConstructorArgValue("value").getBeanDefinition();
|
||||
context.registerBeanDefinition("test", bd);
|
||||
context.refreshForAotProcessing();
|
||||
assertThat(context.getBeanFactory().getMergedBeanDefinition("test")
|
||||
.hasAttribute("mbdppCalled")).isTrue();
|
||||
assertThat(context.getBean("test")).isEqualTo("42");
|
||||
}
|
||||
|
||||
@Test
|
||||
void refreshForAotFailsOnAnActiveContext() {
|
||||
GenericApplicationContext context = new GenericApplicationContext();
|
||||
|
|
|
|||
Loading…
Reference in New Issue