Restore support of list of inner bean definitions

This commit restores the support of multiple bean definitions being
specified in a `List` as a property value or constructor argument.

Rather than handling inner bean definitions externally, there are now
supported by BeanDefinitionPropertiesCodeGenerator, and list of such
type is handled transparently.

Closes gh-29075
This commit is contained in:
Stephane Nicoll
2022-10-18 12:50:54 +02:00
parent 6bdf0bcc4a
commit 6d688e196d
8 changed files with 136 additions and 60 deletions

View File

@@ -66,8 +66,7 @@ class BeanDefinitionMethodGeneratorFactoryTests {
RegisteredBean registeredBean = registerTestBean(beanFactory);
BeanDefinitionMethodGeneratorFactory methodGeneratorFactory = new BeanDefinitionMethodGeneratorFactory(
AotServices.factoriesAndBeans(springFactoriesLoader, beanFactory));
assertThat(methodGeneratorFactory.getBeanDefinitionMethodGenerator(registeredBean,
null)).isNull();
assertThat(methodGeneratorFactory.getBeanDefinitionMethodGenerator(registeredBean)).isNull();
}
@Test
@@ -79,8 +78,7 @@ class BeanDefinitionMethodGeneratorFactoryTests {
new MockBeanRegistrationExcludeFilter(true, 0));
BeanDefinitionMethodGeneratorFactory methodGeneratorFactory = new BeanDefinitionMethodGeneratorFactory(
AotServices.factoriesAndBeans(springFactoriesLoader, beanFactory));
assertThat(methodGeneratorFactory.getBeanDefinitionMethodGenerator(registeredBean,
null)).isNull();
assertThat(methodGeneratorFactory.getBeanDefinitionMethodGenerator(registeredBean)).isNull();
}
@Test
@@ -100,8 +98,7 @@ class BeanDefinitionMethodGeneratorFactoryTests {
RegisteredBean registeredBean = registerTestBean(beanFactory);
BeanDefinitionMethodGeneratorFactory methodGeneratorFactory = new BeanDefinitionMethodGeneratorFactory(
AotServices.factoriesAndBeans(springFactoriesLoader, beanFactory));
assertThat(methodGeneratorFactory.getBeanDefinitionMethodGenerator(registeredBean,
null)).isNull();
assertThat(methodGeneratorFactory.getBeanDefinitionMethodGenerator(registeredBean)).isNull();
assertThat(filter1.wasCalled()).isTrue();
assertThat(filter2.wasCalled()).isTrue();
assertThat(filter3.wasCalled()).isTrue();
@@ -127,7 +124,7 @@ class BeanDefinitionMethodGeneratorFactoryTests {
BeanDefinitionMethodGeneratorFactory methodGeneratorFactory = new BeanDefinitionMethodGeneratorFactory(
AotServices.factoriesAndBeans(springFactoriesLoader, beanFactory));
BeanDefinitionMethodGenerator methodGenerator = methodGeneratorFactory
.getBeanDefinitionMethodGenerator(registeredBean, null);
.getBeanDefinitionMethodGenerator(registeredBean);
assertThat(methodGenerator).extracting("aotContributions").asList()
.containsExactly(beanContribution, loaderContribution);
}
@@ -144,8 +141,8 @@ class BeanDefinitionMethodGeneratorFactoryTests {
RegisteredBean registeredBean2 = RegisteredBean.of(beanFactory, "test2");
BeanDefinitionMethodGeneratorFactory methodGeneratorFactory = new BeanDefinitionMethodGeneratorFactory(
AotServices.factoriesAndBeans(springFactoriesLoader, beanFactory));
assertThat(methodGeneratorFactory.getBeanDefinitionMethodGenerator(registeredBean1, null)).isNull();
assertThat(methodGeneratorFactory.getBeanDefinitionMethodGenerator(registeredBean2, null)).isNull();
assertThat(methodGeneratorFactory.getBeanDefinitionMethodGenerator(registeredBean1)).isNull();
assertThat(methodGeneratorFactory.getBeanDefinitionMethodGenerator(registeredBean2)).isNull();
}
@Test
@@ -157,7 +154,7 @@ class BeanDefinitionMethodGeneratorFactoryTests {
RegisteredBean registeredBean1 = RegisteredBean.of(beanFactory, "test");
BeanDefinitionMethodGeneratorFactory methodGeneratorFactory = new BeanDefinitionMethodGeneratorFactory(
AotServices.factoriesAndBeans(springFactoriesLoader, beanFactory));
assertThat(methodGeneratorFactory.getBeanDefinitionMethodGenerator(registeredBean1, null)).isNotNull();
assertThat(methodGeneratorFactory.getBeanDefinitionMethodGenerator(registeredBean1)).isNotNull();
}
private RegisteredBean registerTestBean(DefaultListableBeanFactory beanFactory) {

View File

@@ -38,6 +38,7 @@ import org.springframework.beans.factory.config.ConstructorArgumentValues.ValueH
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.beans.factory.support.InstanceSupplier;
import org.springframework.beans.factory.support.ManagedList;
import org.springframework.beans.factory.support.RegisteredBean;
import org.springframework.beans.factory.support.RootBeanDefinition;
import org.springframework.beans.testfixture.beans.AnnotatedBean;
@@ -380,6 +381,37 @@ class BeanDefinitionMethodGeneratorTests {
});
}
@SuppressWarnings("unchecked")
@Test
void generateBeanDefinitionMethodWhenHasListOfInnerBeansPropertyValueGeneratesMethod() {
RootBeanDefinition firstInnerBeanDefinition = (RootBeanDefinition) BeanDefinitionBuilder
.rootBeanDefinition(TestBean.class).addPropertyValue("name", "one")
.getBeanDefinition();
RootBeanDefinition secondInnerBeanDefinition = (RootBeanDefinition) BeanDefinitionBuilder
.rootBeanDefinition(TestBean.class).addPropertyValue("name", "two")
.getBeanDefinition();
ManagedList<RootBeanDefinition> list = new ManagedList<>();
list.add(firstInnerBeanDefinition);
list.add(secondInnerBeanDefinition);
RootBeanDefinition beanDefinition = new RootBeanDefinition(TestBean.class);
beanDefinition.getPropertyValues().add("someList", list);
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) -> {
ManagedList<RootBeanDefinition> actualPropertyValue = (ManagedList<RootBeanDefinition>) actual
.getPropertyValues().get("someList");
assertThat(actualPropertyValue).isNotNull().hasSize(2);
assertThat(actualPropertyValue.get(0).getPropertyValues().get("name")).isEqualTo("one");
assertThat(actualPropertyValue.get(1).getPropertyValues().get("name")).isEqualTo("two");
assertThat(compiled.getSourceFileFromPackage(TestBean.class.getPackageName()))
.contains("getSomeListBeanDefinition()", "getSomeListBeanDefinition1()");
});
}
@Test
void generateBeanDefinitionMethodWhenHasInnerBeanConstructorValueGeneratesMethod() {
RootBeanDefinition innerBeanDefinition = (RootBeanDefinition) BeanDefinitionBuilder

View File

@@ -64,12 +64,15 @@ import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException
*/
class BeanDefinitionPropertyValueCodeGeneratorTests {
private static BeanDefinitionPropertyValueCodeGenerator createPropertyValuesCodeGenerator(GeneratedClass generatedClass) {
return new BeanDefinitionPropertyValueCodeGenerator(generatedClass.getMethods(), null);
}
private void compile(Object value, BiConsumer<Object, Compiled> result) {
TestGenerationContext generationContext = new TestGenerationContext();
DeferredTypeBuilder typeBuilder = new DeferredTypeBuilder();
GeneratedClass generatedClass = generationContext.getGeneratedClasses().addForFeature("TestCode", typeBuilder);
CodeBlock generatedCode = new BeanDefinitionPropertyValueCodeGenerator(
generatedClass.getMethods()).generateCode(value);
CodeBlock generatedCode = createPropertyValuesCodeGenerator(generatedClass).generateCode(value);
typeBuilder.set(type -> {
type.addModifiers(Modifier.PUBLIC);
type.addSuperinterface(
@@ -544,8 +547,7 @@ class BeanDefinitionPropertyValueCodeGeneratorTests {
TestGenerationContext context = new TestGenerationContext();
GeneratedClass generatedClass = context.getGeneratedClasses()
.addForFeature("Test", type -> {});
new BeanDefinitionPropertyValueCodeGenerator(generatedClass.getMethods())
.generateCode(value);
createPropertyValuesCodeGenerator(generatedClass).generateCode(value);
}
record SampleValue(String name) {}