From d5732fed451416dc3d2f35f2b77186329f3910f6 Mon Sep 17 00:00:00 2001 From: Juergen Hoeller Date: Thu, 1 Dec 2022 17:46:31 +0100 Subject: [PATCH] Polishing --- .../aot/BeanDefinitionMethodGenerator.java | 17 ++--- .../BeanDefinitionMethodGeneratorFactory.java | 18 ++--- ...eanRegistrationCodeFragmentsDecorator.java | 10 ++- .../aot/BeanRegistrationsAotProcessor.java | 8 ++- .../BeanDefinitionMethodGeneratorTests.java | 72 ++++++++----------- .../ConfigurationClassPostProcessor.java | 1 + 6 files changed, 56 insertions(+), 70 deletions(-) diff --git a/spring-beans/src/main/java/org/springframework/beans/factory/aot/BeanDefinitionMethodGenerator.java b/spring-beans/src/main/java/org/springframework/beans/factory/aot/BeanDefinitionMethodGenerator.java index 4ef2debf2d6..94951852b94 100644 --- a/spring-beans/src/main/java/org/springframework/beans/factory/aot/BeanDefinitionMethodGenerator.java +++ b/spring-beans/src/main/java/org/springframework/beans/factory/aot/BeanDefinitionMethodGenerator.java @@ -134,10 +134,12 @@ class BeanDefinitionMethodGenerator { type.addJavadoc("Bean definitions for {@link $T}", topLevelClassName); type.addModifiers(Modifier.PUBLIC); }); + List names = target.simpleNames(); if (names.size() == 1) { return generatedClass; } + List namesToProcess = names.subList(1, names.size()); ClassName currentTargetClassName = topLevelClassName; GeneratedClass tmp = generatedClass; @@ -148,8 +150,7 @@ class BeanDefinitionMethodGenerator { return tmp; } - private static GeneratedClass createInnerClass(GeneratedClass generatedClass, - String name, ClassName target) { + private static GeneratedClass createInnerClass(GeneratedClass generatedClass, String name, ClassName target) { return generatedClass.getOrAdd(name, type -> { type.addJavadoc("Bean definitions for {@link $T}", target); type.addModifiers(Modifier.PUBLIC, Modifier.STATIC); @@ -167,16 +168,16 @@ class BeanDefinitionMethodGenerator { return codeFragments; } - private GeneratedMethod generateBeanDefinitionMethod( - GenerationContext generationContext, ClassName className, - GeneratedMethods generatedMethods, BeanRegistrationCodeFragments codeFragments, - Modifier modifier) { + private GeneratedMethod generateBeanDefinitionMethod(GenerationContext generationContext, + ClassName className, GeneratedMethods generatedMethods, + BeanRegistrationCodeFragments codeFragments, Modifier modifier) { BeanRegistrationCodeGenerator codeGenerator = new BeanRegistrationCodeGenerator( className, generatedMethods, this.registeredBean, this.constructorOrFactoryMethod, codeFragments); - this.aotContributions.forEach(aotContribution -> aotContribution - .applyTo(generationContext, codeGenerator)); + + this.aotContributions.forEach(aotContribution -> aotContribution.applyTo(generationContext, codeGenerator)); + return generatedMethods.add("getBeanDefinition", method -> { method.addJavadoc("Get the $L definition for '$L'", (!this.registeredBean.isInnerBean()) ? "bean" : "inner-bean", diff --git a/spring-beans/src/main/java/org/springframework/beans/factory/aot/BeanDefinitionMethodGeneratorFactory.java b/spring-beans/src/main/java/org/springframework/beans/factory/aot/BeanDefinitionMethodGeneratorFactory.java index 73f34e71abe..580a0533ced 100644 --- a/spring-beans/src/main/java/org/springframework/beans/factory/aot/BeanDefinitionMethodGeneratorFactory.java +++ b/spring-beans/src/main/java/org/springframework/beans/factory/aot/BeanDefinitionMethodGeneratorFactory.java @@ -87,8 +87,7 @@ class BeanDefinitionMethodGeneratorFactory { * {@link BeanRegistrationAotProcessor} provided contributions. * @param registeredBean the registered bean * @param currentPropertyName the property name that this bean belongs to - * @return a new {@link BeanDefinitionMethodGenerator} instance or - * {@code null} + * @return a new {@link BeanDefinitionMethodGenerator} instance or {@code null} */ @Nullable BeanDefinitionMethodGenerator getBeanDefinitionMethodGenerator( @@ -97,8 +96,7 @@ class BeanDefinitionMethodGeneratorFactory { if (isExcluded(registeredBean)) { return null; } - List contributions = getAotContributions( - registeredBean); + List contributions = getAotContributions(registeredBean); return new BeanDefinitionMethodGenerator(this, registeredBean, currentPropertyName, contributions); } @@ -110,8 +108,7 @@ class BeanDefinitionMethodGeneratorFactory { * {@link BeanDefinitionMethodGenerator} will include all * {@link BeanRegistrationAotProcessor} provided contributions. * @param registeredBean the registered bean - * @return a new {@link BeanDefinitionMethodGenerator} instance or - * {@code null} + * @return a new {@link BeanDefinitionMethodGenerator} instance or {@code null} */ @Nullable BeanDefinitionMethodGenerator getBeanDefinitionMethodGenerator(RegisteredBean registeredBean) { @@ -142,19 +139,16 @@ class BeanDefinitionMethodGeneratorFactory { } if (BeanRegistrationAotProcessor.class.isAssignableFrom(beanClass)) { BeanRegistrationAotProcessor processor = this.aotProcessors.findByBeanName(registeredBean.getBeanName()); - return (processor == null) || processor.isBeanExcludedFromAotProcessing(); + return (processor == null || processor.isBeanExcludedFromAotProcessing()); } return false; } - private List getAotContributions( - RegisteredBean registeredBean) { - + private List getAotContributions(RegisteredBean registeredBean) { String beanName = registeredBean.getBeanName(); List contributions = new ArrayList<>(); for (BeanRegistrationAotProcessor aotProcessor : this.aotProcessors) { - BeanRegistrationAotContribution contribution = aotProcessor - .processAheadOfTime(registeredBean); + BeanRegistrationAotContribution contribution = aotProcessor.processAheadOfTime(registeredBean); if (contribution != null) { logger.trace(LogMessage.format( "Adding bean registration AOT contribution %S from %S to '%S'", diff --git a/spring-beans/src/main/java/org/springframework/beans/factory/aot/BeanRegistrationCodeFragmentsDecorator.java b/spring-beans/src/main/java/org/springframework/beans/factory/aot/BeanRegistrationCodeFragmentsDecorator.java index 69cae124b8f..e4ff961262e 100644 --- a/spring-beans/src/main/java/org/springframework/beans/factory/aot/BeanRegistrationCodeFragmentsDecorator.java +++ b/spring-beans/src/main/java/org/springframework/beans/factory/aot/BeanRegistrationCodeFragmentsDecorator.java @@ -64,8 +64,7 @@ public class BeanRegistrationCodeFragmentsDecorator implements BeanRegistrationC } @Override - public CodeBlock generateSetBeanDefinitionPropertiesCode( - GenerationContext generationContext, + public CodeBlock generateSetBeanDefinitionPropertiesCode(GenerationContext generationContext, BeanRegistrationCode beanRegistrationCode, RootBeanDefinition beanDefinition, Predicate attributeFilter) { @@ -74,8 +73,7 @@ public class BeanRegistrationCodeFragmentsDecorator implements BeanRegistrationC } @Override - public CodeBlock generateSetBeanInstanceSupplierCode( - GenerationContext generationContext, + public CodeBlock generateSetBeanInstanceSupplierCode(GenerationContext generationContext, BeanRegistrationCode beanRegistrationCode, CodeBlock instanceSupplierCode, List postProcessors) { @@ -85,8 +83,8 @@ public class BeanRegistrationCodeFragmentsDecorator implements BeanRegistrationC @Override public CodeBlock generateInstanceSupplierCode(GenerationContext generationContext, - BeanRegistrationCode beanRegistrationCode, - Executable constructorOrFactoryMethod, boolean allowDirectSupplierShortcut) { + BeanRegistrationCode beanRegistrationCode, Executable constructorOrFactoryMethod, + boolean allowDirectSupplierShortcut) { return this.delegate.generateInstanceSupplierCode(generationContext, beanRegistrationCode, constructorOrFactoryMethod, allowDirectSupplierShortcut); diff --git a/spring-beans/src/main/java/org/springframework/beans/factory/aot/BeanRegistrationsAotProcessor.java b/spring-beans/src/main/java/org/springframework/beans/factory/aot/BeanRegistrationsAotProcessor.java index cbbdcf0680e..63bcf2fccce 100644 --- a/spring-beans/src/main/java/org/springframework/beans/factory/aot/BeanRegistrationsAotProcessor.java +++ b/spring-beans/src/main/java/org/springframework/beans/factory/aot/BeanRegistrationsAotProcessor.java @@ -22,6 +22,7 @@ import java.util.Map; import org.springframework.beans.factory.aot.BeanRegistrationsAotContribution.Registration; import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; import org.springframework.beans.factory.support.RegisteredBean; +import org.springframework.lang.Nullable; /** * {@link BeanFactoryInitializationAotProcessor} that contributes code to @@ -35,19 +36,22 @@ import org.springframework.beans.factory.support.RegisteredBean; class BeanRegistrationsAotProcessor implements BeanFactoryInitializationAotProcessor { @Override + @Nullable public BeanRegistrationsAotContribution processAheadOfTime(ConfigurableListableBeanFactory beanFactory) { BeanDefinitionMethodGeneratorFactory beanDefinitionMethodGeneratorFactory = new BeanDefinitionMethodGeneratorFactory(beanFactory); Map registrations = new LinkedHashMap<>(); + for (String beanName : beanFactory.getBeanDefinitionNames()) { RegisteredBean registeredBean = RegisteredBean.of(beanFactory, beanName); - BeanDefinitionMethodGenerator beanDefinitionMethodGenerator = beanDefinitionMethodGeneratorFactory - .getBeanDefinitionMethodGenerator(registeredBean); + BeanDefinitionMethodGenerator beanDefinitionMethodGenerator = + beanDefinitionMethodGeneratorFactory.getBeanDefinitionMethodGenerator(registeredBean); if (beanDefinitionMethodGenerator != null) { registrations.put(beanName, new Registration(beanDefinitionMethodGenerator, beanFactory.getAliases(beanName))); } } + if (registrations.isEmpty()) { return null; } diff --git a/spring-beans/src/test/java/org/springframework/beans/factory/aot/BeanDefinitionMethodGeneratorTests.java b/spring-beans/src/test/java/org/springframework/beans/factory/aot/BeanDefinitionMethodGeneratorTests.java index d90f7534e32..f0d79dcad1a 100644 --- a/spring-beans/src/test/java/org/springframework/beans/factory/aot/BeanDefinitionMethodGeneratorTests.java +++ b/spring-beans/src/test/java/org/springframework/beans/factory/aot/BeanDefinitionMethodGeneratorTests.java @@ -88,8 +88,7 @@ class BeanDefinitionMethodGeneratorTests { @Test void generateBeanDefinitionMethodGeneratesMethod() { - RegisteredBean registeredBean = registerBean( - new RootBeanDefinition(TestBean.class)); + RegisteredBean registeredBean = registerBean(new RootBeanDefinition(TestBean.class)); BeanDefinitionMethodGenerator generator = new BeanDefinitionMethodGenerator( this.methodGeneratorFactory, registeredBean, null, Collections.emptyList()); @@ -172,10 +171,8 @@ class BeanDefinitionMethodGeneratorTests { @Test void generateBeanDefinitionMethodWhenHasInstancePostProcessorGeneratesMethod() { - RegisteredBean registeredBean = registerBean( - new RootBeanDefinition(TestBean.class)); - BeanRegistrationAotContribution aotContribution = (generationContext, - beanRegistrationCode) -> { + RegisteredBean registeredBean = registerBean(new RootBeanDefinition(TestBean.class)); + BeanRegistrationAotContribution aotContribution = (generationContext, beanRegistrationCode) -> { GeneratedMethod generatedMethod = beanRegistrationCode.getMethods().add("postProcess", method -> method.addModifiers(Modifier.STATIC) .addParameter(RegisteredBean.class, "registeredBean") @@ -183,16 +180,14 @@ class BeanDefinitionMethodGeneratorTests { .returns(TestBean.class).addCode("return new $T($S);", TestBean.class, "postprocessed")); beanRegistrationCode.addInstancePostProcessor(generatedMethod.toMethodReference()); }; - List aotContributions = Collections - .singletonList(aotContribution); + List aotContributions = Collections.singletonList(aotContribution); BeanDefinitionMethodGenerator generator = new BeanDefinitionMethodGenerator( this.methodGeneratorFactory, registeredBean, null, aotContributions); MethodReference method = generator.generateBeanDefinitionMethod( this.generationContext, this.beanRegistrationsCode); compile(method, (actual, compiled) -> { assertThat(actual.getBeanClass()).isEqualTo(TestBean.class); - InstanceSupplier supplier = (InstanceSupplier) actual - .getInstanceSupplier(); + InstanceSupplier supplier = (InstanceSupplier) actual.getInstanceSupplier(); try { TestBean instance = (TestBean) supplier.get(registeredBean); assertThat(instance.getName()).isEqualTo("postprocessed"); @@ -204,9 +199,10 @@ class BeanDefinitionMethodGeneratorTests { }); } - @Test // gh-28748 + @Test // gh-28748 void generateBeanDefinitionMethodWhenHasInstancePostProcessorAndFactoryMethodGeneratesMethod() { - this.beanFactory.registerBeanDefinition("testBeanConfiguration", new RootBeanDefinition(TestBeanConfiguration.class)); + this.beanFactory.registerBeanDefinition("testBeanConfiguration", + new RootBeanDefinition(TestBeanConfiguration.class)); RootBeanDefinition beanDefinition = new RootBeanDefinition(TestBean.class); beanDefinition.setFactoryBeanName("testBeanConfiguration"); beanDefinition.setFactoryMethodName("testBean"); @@ -220,8 +216,7 @@ class BeanDefinitionMethodGeneratorTests { .returns(TestBean.class).addCode("return new $T($S);", TestBean.class, "postprocessed")); beanRegistrationCode.addInstancePostProcessor(generatedMethod.toMethodReference()); }; - List aotContributions = Collections - .singletonList(aotContribution); + List aotContributions = Collections.singletonList(aotContribution); BeanDefinitionMethodGenerator generator = new BeanDefinitionMethodGenerator( this.methodGeneratorFactory, registeredBean, null, aotContributions); MethodReference method = generator.generateBeanDefinitionMethod( @@ -244,10 +239,9 @@ class BeanDefinitionMethodGeneratorTests { @Test void generateBeanDefinitionMethodWhenHasCodeFragmentsCustomizerGeneratesMethod() { - RegisteredBean registeredBean = registerBean( - new RootBeanDefinition(TestBean.class)); - BeanRegistrationAotContribution aotContribution = BeanRegistrationAotContribution - .withCustomCodeFragments(this::customizeBeanDefinitionCode); + RegisteredBean registeredBean = registerBean(new RootBeanDefinition(TestBean.class)); + BeanRegistrationAotContribution aotContribution = + BeanRegistrationAotContribution.withCustomCodeFragments(this::customizeBeanDefinitionCode); List aotContributions = Collections.singletonList(aotContribution); BeanDefinitionMethodGenerator generator = new BeanDefinitionMethodGenerator( this.methodGeneratorFactory, registeredBean, null, aotContributions); @@ -260,21 +254,16 @@ class BeanDefinitionMethodGeneratorTests { }); } - private BeanRegistrationCodeFragments customizeBeanDefinitionCode( - BeanRegistrationCodeFragments codeFragments) { + private BeanRegistrationCodeFragments customizeBeanDefinitionCode(BeanRegistrationCodeFragments codeFragments) { return new BeanRegistrationCodeFragmentsDecorator(codeFragments) { - @Override - public CodeBlock generateNewBeanDefinitionCode( - GenerationContext generationContext, - ResolvableType beanType, - BeanRegistrationCode beanRegistrationCode) { + public CodeBlock generateNewBeanDefinitionCode(GenerationContext generationContext, + ResolvableType beanType, BeanRegistrationCode beanRegistrationCode) { CodeBlock.Builder code = CodeBlock.builder(); code.addStatement("// I am custom"); code.add(super.generateNewBeanDefinitionCode(generationContext, beanType, beanRegistrationCode)); return code.build(); } - }; } @@ -301,10 +290,9 @@ class BeanDefinitionMethodGeneratorTests { beanDefinition.setAttribute("a", "A"); beanDefinition.setAttribute("b", "B"); RegisteredBean registeredBean = registerBean(beanDefinition); - BeanRegistrationAotContribution aotContribution = BeanRegistrationAotContribution - .withCustomCodeFragments(this::customizeAttributeFilter); - List aotContributions = Collections - .singletonList(aotContribution); + BeanRegistrationAotContribution aotContribution = + BeanRegistrationAotContribution.withCustomCodeFragments(this::customizeAttributeFilter); + List aotContributions = Collections.singletonList(aotContribution); BeanDefinitionMethodGenerator generator = new BeanDefinitionMethodGenerator( this.methodGeneratorFactory, registeredBean, null, aotContributions); @@ -316,20 +304,15 @@ class BeanDefinitionMethodGeneratorTests { }); } - private BeanRegistrationCodeFragments customizeAttributeFilter( - BeanRegistrationCodeFragments codeFragments) { + private BeanRegistrationCodeFragments customizeAttributeFilter(BeanRegistrationCodeFragments codeFragments) { return new BeanRegistrationCodeFragmentsDecorator(codeFragments) { - @Override - public CodeBlock generateSetBeanDefinitionPropertiesCode( - GenerationContext generationContext, - BeanRegistrationCode beanRegistrationCode, - RootBeanDefinition beanDefinition, + public CodeBlock generateSetBeanDefinitionPropertiesCode(GenerationContext generationContext, + BeanRegistrationCode beanRegistrationCode, RootBeanDefinition beanDefinition, Predicate attributeFilter) { return super.generateSetBeanDefinitionPropertiesCode(generationContext, beanRegistrationCode, beanDefinition, "a"::equals); } - }; } @@ -471,8 +454,7 @@ class BeanDefinitionMethodGeneratorTests { @Test @CompileWithForkedClassLoader void generateBeanDefinitionMethodWhenPackagePrivateBean() { - RegisteredBean registeredBean = registerBean( - new RootBeanDefinition(PackagePrivateTestBean.class)); + RegisteredBean registeredBean = registerBean(new RootBeanDefinition(PackagePrivateTestBean.class)); BeanDefinitionMethodGenerator generator = new BeanDefinitionMethodGenerator( this.methodGeneratorFactory, registeredBean, null, Collections.emptyList()); @@ -502,6 +484,13 @@ class BeanDefinitionMethodGeneratorTests { testBeanDefinitionMethodInCurrentFile(DocumentBuilderFactory.class, beanDefinition); } + @Test + void generateBeanDefinitionMethodWhenBeanIsOfPrimitiveType() { + RootBeanDefinition beanDefinition = (RootBeanDefinition) BeanDefinitionBuilder + .rootBeanDefinition(Boolean.class).setFactoryMethod("parseBoolean").addConstructorArgValue("true").getBeanDefinition(); + testBeanDefinitionMethodInCurrentFile(Boolean.class, beanDefinition); + } + private void testBeanDefinitionMethodInCurrentFile(Class targetType, RootBeanDefinition beanDefinition) { RegisteredBean registeredBean = registerBean(new RootBeanDefinition(beanDefinition)); BeanDefinitionMethodGenerator generator = new BeanDefinitionMethodGenerator( @@ -525,8 +514,7 @@ class BeanDefinitionMethodGeneratorTests { return RegisteredBean.of(this.beanFactory, beanName); } - private void compile(MethodReference method, - BiConsumer result) { + private void compile(MethodReference method, BiConsumer result) { this.beanRegistrationsCode.getTypeBuilder().set(type -> { CodeBlock methodInvocation = method.toInvokeCodeBlock(ArgumentCodeGenerator.none(), this.beanRegistrationsCode.getClassName()); diff --git a/spring-context/src/main/java/org/springframework/context/annotation/ConfigurationClassPostProcessor.java b/spring-context/src/main/java/org/springframework/context/annotation/ConfigurationClassPostProcessor.java index 6c06e366c2b..94995830b97 100644 --- a/spring-context/src/main/java/org/springframework/context/annotation/ConfigurationClassPostProcessor.java +++ b/spring-context/src/main/java/org/springframework/context/annotation/ConfigurationClassPostProcessor.java @@ -319,6 +319,7 @@ public class ConfigurationClassPostProcessor implements BeanDefinitionRegistryPo } @Override + @Nullable public BeanFactoryInitializationAotContribution processAheadOfTime(ConfigurableListableBeanFactory beanFactory) { boolean hasPropertySourceDescriptors = !CollectionUtils.isEmpty(this.propertySourceDescriptors); boolean hasImportRegistry = beanFactory.containsBean(IMPORT_REGISTRY_BEAN_NAME);