Generate matching structure for configuration classes

This commit improves GeneratedClass to support inner classes, allowing
them to be registered by name with a type customizer, as
GeneratedClasses does for top level classes.

BeanDefinitionMethodGenerator leverages this feature to create a
matching structure for configuration classes that contain inner classes.

Closes gh-29213
This commit is contained in:
Stephane Nicoll
2022-09-28 08:55:27 +02:00
parent b1ee44f12e
commit 38d91bafce
6 changed files with 230 additions and 18 deletions

View File

@@ -42,7 +42,9 @@ import org.springframework.beans.factory.support.RootBeanDefinition;
import org.springframework.beans.testfixture.beans.AnnotatedBean;
import org.springframework.beans.testfixture.beans.GenericBean;
import org.springframework.beans.testfixture.beans.TestBean;
import org.springframework.beans.testfixture.beans.factory.aot.InnerBeanConfiguration;
import org.springframework.beans.testfixture.beans.factory.aot.MockBeanRegistrationsCode;
import org.springframework.beans.testfixture.beans.factory.aot.SimpleBean;
import org.springframework.core.ResolvableType;
import org.springframework.core.test.io.support.MockSpringFactoriesLoader;
import org.springframework.core.test.tools.CompileWithForkedClassLoader;
@@ -60,6 +62,7 @@ import static org.assertj.core.api.Assertions.assertThat;
* {@link DefaultBeanRegistrationCodeFragments}.
*
* @author Phillip Webb
* @author Stephane Nicoll
*/
class BeanDefinitionMethodGeneratorTests {
@@ -99,6 +102,52 @@ class BeanDefinitionMethodGeneratorTests {
});
}
@Test
void generateBeanDefinitionMethodWhenHasInnerClassTargetMethodGeneratesMethod() {
this.beanFactory.registerBeanDefinition("testBeanConfiguration", new RootBeanDefinition(
InnerBeanConfiguration.Simple.class));
RootBeanDefinition beanDefinition = new RootBeanDefinition(SimpleBean.class);
beanDefinition.setFactoryBeanName("testBeanConfiguration");
beanDefinition.setFactoryMethodName("simpleBean");
RegisteredBean registeredBean = registerBean(beanDefinition);
BeanDefinitionMethodGenerator generator = new BeanDefinitionMethodGenerator(
this.methodGeneratorFactory, registeredBean, null,
Collections.emptyList());
MethodReference method = generator.generateBeanDefinitionMethod(
this.generationContext, this.beanRegistrationsCode);
compile(method, (actual, compiled) -> {
SourceFile sourceFile = compiled.getSourceFile(".*BeanDefinitions");
assertThat(sourceFile.getClassName()).endsWith("InnerBeanConfiguration__BeanDefinitions");
assertThat(sourceFile).contains("public static class Simple__BeanDefinitions")
.contains("Bean definitions for {@link InnerBeanConfiguration.Simple}")
.doesNotContain("Another__BeanDefinitions");
});
}
@Test
void generateBeanDefinitionMethodWhenHasNestedInnerClassTargetMethodGeneratesMethod() {
this.beanFactory.registerBeanDefinition("testBeanConfiguration", new RootBeanDefinition(
InnerBeanConfiguration.Simple.Another.class));
RootBeanDefinition beanDefinition = new RootBeanDefinition(SimpleBean.class);
beanDefinition.setFactoryBeanName("testBeanConfiguration");
beanDefinition.setFactoryMethodName("anotherBean");
RegisteredBean registeredBean = registerBean(beanDefinition);
BeanDefinitionMethodGenerator generator = new BeanDefinitionMethodGenerator(
this.methodGeneratorFactory, registeredBean, null,
Collections.emptyList());
MethodReference method = generator.generateBeanDefinitionMethod(
this.generationContext, this.beanRegistrationsCode);
compile(method, (actual, compiled) -> {
SourceFile sourceFile = compiled.getSourceFile(".*BeanDefinitions");
assertThat(sourceFile.getClassName()).endsWith("InnerBeanConfiguration__BeanDefinitions");
assertThat(sourceFile).contains("public static class Simple__BeanDefinitions")
.contains("Bean definitions for {@link InnerBeanConfiguration.Simple}")
.contains("public static class Another__BeanDefinitions")
.contains("Bean definitions for {@link InnerBeanConfiguration.Simple.Another}");
});
}
@Test
void generateBeanDefinitionMethodWhenHasGenericsGeneratesMethod() {
RegisteredBean registeredBean = registerBean(new RootBeanDefinition(