Add support for ImportAware in BeanRegistrar

Closes gh-34627
This commit is contained in:
Sébastien Deleuze
2025-03-21 11:49:15 +01:00
parent 3e788e4ca1
commit 5ce64f47b2
10 changed files with 196 additions and 21 deletions

View File

@@ -500,6 +500,22 @@ public class ConfigurationClassPostProcessorAotContributionTests {
});
}
@Test
void applyToWhenIsImportAware() {
BeanFactoryInitializationAotContribution contribution = getContribution(CommonAnnotationBeanPostProcessor.class,
ImportAwareBeanRegistrarConfiguration.class);
assertThat(contribution).isNotNull();
contribution.applyTo(generationContext, beanFactoryInitializationCode);
compile((initializer, compiled) -> {
GenericApplicationContext freshContext = new GenericApplicationContext();
initializer.accept(freshContext);
freshContext.refresh();
assertThat(freshContext.getBean(ClassNameHolder.class).className())
.isEqualTo(ImportAwareBeanRegistrarConfiguration.class.getName());
freshContext.close();
});
}
@SuppressWarnings("unchecked")
private void compile(BiConsumer<Consumer<GenericApplicationContext>, Compiled> result) {
MethodReference methodReference = beanFactoryInitializationCode.getInitializers().get(0);
@@ -561,6 +577,31 @@ public class ConfigurationClassPostProcessorAotContributionTests {
}
}
@Import(ImportAwareBeanRegistrar.class)
public static class ImportAwareBeanRegistrarConfiguration {
}
public static class ImportAwareBeanRegistrar implements BeanRegistrar, ImportAware {
@Nullable
private AnnotationMetadata importMetadata;
@Override
public void register(BeanRegistry registry, Environment env) {
registry.registerBean(ClassNameHolder.class, spec -> spec.supplier(context ->
new ClassNameHolder(this.importMetadata == null ? null : this.importMetadata.getClassName())));
}
@Override
public void setImportMetadata(AnnotationMetadata importMetadata) {
this.importMetadata = importMetadata;
}
public @Nullable AnnotationMetadata getImportMetadata() {
return this.importMetadata;
}
}
static class Foo {
}
@@ -576,6 +617,8 @@ public class ConfigurationClassPostProcessorAotContributionTests {
}
public record ClassNameHolder(@Nullable String className) {}
private @Nullable BeanFactoryInitializationAotContribution getContribution(Class<?>... types) {
DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();

View File

@@ -24,12 +24,14 @@ import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.support.RootBeanDefinition;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.testfixture.beans.factory.GenericBeanRegistrar;
import org.springframework.context.testfixture.beans.factory.ImportAwareBeanRegistrar;
import org.springframework.context.testfixture.beans.factory.SampleBeanRegistrar.Bar;
import org.springframework.context.testfixture.beans.factory.SampleBeanRegistrar.Baz;
import org.springframework.context.testfixture.beans.factory.SampleBeanRegistrar.Foo;
import org.springframework.context.testfixture.beans.factory.SampleBeanRegistrar.Init;
import org.springframework.context.testfixture.context.annotation.registrar.BeanRegistrarConfiguration;
import org.springframework.context.testfixture.context.annotation.registrar.GenericBeanRegistrarConfiguration;
import org.springframework.context.testfixture.context.annotation.registrar.ImportAwareBeanRegistrarConfiguration;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
@@ -82,4 +84,13 @@ public class BeanRegistrarConfigurationTests {
assertThat(beanDefinition.getResolvableType().resolveGeneric(0)).isEqualTo(GenericBeanRegistrar.Foo.class);
}
@Test
void beanRegistrarWithImportAware() {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
context.register(ImportAwareBeanRegistrarConfiguration.class);
context.refresh();
assertThat(context.getBean(ImportAwareBeanRegistrar.ClassNameHolder.class).className())
.isEqualTo(ImportAwareBeanRegistrarConfiguration.class.getName());
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2024 the original author or authors.
* Copyright 2002-2025 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -46,6 +46,8 @@ import org.springframework.beans.factory.support.MergedBeanDefinitionPostProcess
import org.springframework.beans.factory.support.RootBeanDefinition;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.testfixture.beans.factory.ImportAwareBeanRegistrar;
import org.springframework.context.testfixture.beans.factory.SampleBeanRegistrar;
import org.springframework.core.DecoratingProxy;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.core.env.Environment;
@@ -627,6 +629,22 @@ class GenericApplicationContextTests {
context.close();
}
@Test
void beanRegistrar() {
GenericApplicationContext context = new GenericApplicationContext();
context.register(new SampleBeanRegistrar());
context.refresh();
assertThat(context.getBean(SampleBeanRegistrar.Bar.class).foo()).isEqualTo(context.getBean(SampleBeanRegistrar.Foo.class));
}
@Test
void importAwareBeanRegistrar() {
GenericApplicationContext context = new GenericApplicationContext();
context.register(new ImportAwareBeanRegistrar());
context.refresh();
assertThat(context.getBean(ImportAwareBeanRegistrar.ClassNameHolder.class).className()).isNull();
}
private MergedBeanDefinitionPostProcessor registerMockMergedBeanDefinitionPostProcessor(GenericApplicationContext context) {
MergedBeanDefinitionPostProcessor bpp = mock();