diff --git a/spring-aop/src/main/java/org/springframework/aop/scope/ScopedProxyBeanRegistrationAotProcessor.java b/spring-aop/src/main/java/org/springframework/aop/scope/ScopedProxyBeanRegistrationAotProcessor.java index 5ad52df235b..512f06e3fda 100644 --- a/spring-aop/src/main/java/org/springframework/aop/scope/ScopedProxyBeanRegistrationAotProcessor.java +++ b/spring-aop/src/main/java/org/springframework/aop/scope/ScopedProxyBeanRegistrationAotProcessor.java @@ -30,6 +30,7 @@ import org.springframework.beans.factory.aot.BeanRegistrationAotContribution; import org.springframework.beans.factory.aot.BeanRegistrationAotProcessor; import org.springframework.beans.factory.aot.BeanRegistrationCode; import org.springframework.beans.factory.aot.BeanRegistrationCodeFragments; +import org.springframework.beans.factory.aot.BeanRegistrationCodeFragmentsDecorator; import org.springframework.beans.factory.config.BeanDefinition; import org.springframework.beans.factory.config.ConfigurableBeanFactory; import org.springframework.beans.factory.support.InstanceSupplier; @@ -63,9 +64,9 @@ class ScopedProxyBeanRegistrationAotProcessor implements BeanRegistrationAotProc ": no target bean definition found with name " + targetBeanName); return null; } - return BeanRegistrationAotContribution.ofBeanRegistrationCodeFragmentsCustomizer(codeFragments -> - new ScopedProxyBeanRegistrationCodeFragments(codeFragments, registeredBean, - targetBeanName, targetBeanDefinition)); + return BeanRegistrationAotContribution.withCustomCodeFragments(codeFragments -> + new ScopedProxyBeanRegistrationCodeFragments(codeFragments, registeredBean, + targetBeanName, targetBeanDefinition)); } return null; } @@ -87,7 +88,7 @@ class ScopedProxyBeanRegistrationAotProcessor implements BeanRegistrationAotProc } - private static class ScopedProxyBeanRegistrationCodeFragments extends BeanRegistrationCodeFragments { + private static class ScopedProxyBeanRegistrationCodeFragments extends BeanRegistrationCodeFragmentsDecorator { private static final String REGISTERED_BEAN_PARAMETER_NAME = "registeredBean"; @@ -97,10 +98,10 @@ class ScopedProxyBeanRegistrationAotProcessor implements BeanRegistrationAotProc private final BeanDefinition targetBeanDefinition; - ScopedProxyBeanRegistrationCodeFragments(BeanRegistrationCodeFragments codeGenerator, + ScopedProxyBeanRegistrationCodeFragments(BeanRegistrationCodeFragments delegate, RegisteredBean registeredBean, String targetBeanName, BeanDefinition targetBeanDefinition) { - super(codeGenerator); + super(delegate); this.registeredBean = registeredBean; this.targetBeanName = targetBeanName; this.targetBeanDefinition = targetBeanDefinition; diff --git a/spring-beans/src/main/java/org/springframework/beans/factory/aot/BeanRegistrationAotContribution.java b/spring-beans/src/main/java/org/springframework/beans/factory/aot/BeanRegistrationAotContribution.java index d3352d96d66..bf63a64c7b6 100644 --- a/spring-beans/src/main/java/org/springframework/beans/factory/aot/BeanRegistrationAotContribution.java +++ b/spring-beans/src/main/java/org/springframework/beans/factory/aot/BeanRegistrationAotContribution.java @@ -26,6 +26,7 @@ import org.springframework.util.Assert; * a single bean definition. * * @author Phillip Webb + * @author Stephane Nicoll * @since 6.0 * @see BeanRegistrationAotProcessor */ @@ -55,24 +56,23 @@ public interface BeanRegistrationAotContribution { BeanRegistrationCode beanRegistrationCode); /** - * Factory method that can be used to create a - * {@link BeanRegistrationAotContribution} that applies the given - * {@link BeanRegistrationCodeFragments} customizer. - * @param beanRegistrationCodeFragmentsCustomizer the - * {@link BeanRegistrationCodeFragments} customizer + * Create a {@link BeanRegistrationAotContribution} that customizes + * the {@link BeanRegistrationCodeFragments}. Typically used in + * conjunction with an extension of {@link BeanRegistrationCodeFragmentsDecorator} + * that overrides a specific callback. + * @param defaultCodeFragments the default code fragments * @return a new {@link BeanRegistrationAotContribution} instance - * @see #customizeBeanRegistrationCodeFragments(GenerationContext, BeanRegistrationCodeFragments) + * @see BeanRegistrationCodeFragmentsDecorator */ - static BeanRegistrationAotContribution ofBeanRegistrationCodeFragmentsCustomizer( - UnaryOperator beanRegistrationCodeFragmentsCustomizer) { - Assert.notNull(beanRegistrationCodeFragmentsCustomizer, - "BeanRegistrationCodeFragmentsCustomizer must not be null"); + static BeanRegistrationAotContribution withCustomCodeFragments( + UnaryOperator defaultCodeFragments) { + Assert.notNull(defaultCodeFragments, "'defaultCodeFragments' must not be null"); return new BeanRegistrationAotContribution() { @Override public BeanRegistrationCodeFragments customizeBeanRegistrationCodeFragments( GenerationContext generationContext, BeanRegistrationCodeFragments codeFragments) { - return beanRegistrationCodeFragmentsCustomizer.apply(codeFragments); + return defaultCodeFragments.apply(codeFragments); } @Override diff --git a/spring-beans/src/main/java/org/springframework/beans/factory/aot/BeanRegistrationCodeFragments.java b/spring-beans/src/main/java/org/springframework/beans/factory/aot/BeanRegistrationCodeFragments.java index b2469869654..9019cce7b4d 100644 --- a/spring-beans/src/main/java/org/springframework/beans/factory/aot/BeanRegistrationCodeFragments.java +++ b/spring-beans/src/main/java/org/springframework/beans/factory/aot/BeanRegistrationCodeFragments.java @@ -27,46 +27,26 @@ import org.springframework.beans.factory.support.RegisteredBean; import org.springframework.beans.factory.support.RootBeanDefinition; import org.springframework.core.ResolvableType; import org.springframework.javapoet.CodeBlock; -import org.springframework.util.Assert; /** - * Class used to generate the various fragments of code needed to register a - * bean. + * Generate the various fragments of code needed to register a bean. * * @author Phillip Webb * @since 6.0 */ -public abstract class BeanRegistrationCodeFragments { +public interface BeanRegistrationCodeFragments { /** * The variable name to used when creating the bean definition. */ - protected static final String BEAN_DEFINITION_VARIABLE = "beanDefinition"; + String BEAN_DEFINITION_VARIABLE = "beanDefinition"; /** * The variable name to used when creating the bean definition. */ - protected static final String INSTANCE_SUPPLIER_VARIABLE = "instanceSupplier"; + String INSTANCE_SUPPLIER_VARIABLE = "instanceSupplier"; - private final BeanRegistrationCodeFragments codeFragments; - - - protected BeanRegistrationCodeFragments(BeanRegistrationCodeFragments codeFragments) { - Assert.notNull(codeFragments, "'codeFragments' must not be null"); - this.codeFragments = codeFragments; - } - - - /** - * Package-private constructor exclusively for - * {@link DefaultBeanRegistrationCodeFragments}. All methods are overridden - * so {@code this.codeFragments} is never actually used. - */ - BeanRegistrationCodeFragments() { - this.codeFragments = this; - } - /** * Return the target for the registration. Used to determine where to write * the code. @@ -74,11 +54,8 @@ public abstract class BeanRegistrationCodeFragments { * @param constructorOrFactoryMethod the constructor or factory method * @return the target class */ - public Class getTarget(RegisteredBean registeredBean, - Executable constructorOrFactoryMethod) { - - return this.codeFragments.getTarget(registeredBean, constructorOrFactoryMethod); - } + Class getTarget(RegisteredBean registeredBean, + Executable constructorOrFactoryMethod); /** * Generate the code that defines the new bean definition instance. @@ -87,13 +64,8 @@ public abstract class BeanRegistrationCodeFragments { * @param beanRegistrationCode the bean registration code * @return the generated code */ - public CodeBlock generateNewBeanDefinitionCode(GenerationContext generationContext, - ResolvableType beanType, BeanRegistrationCode beanRegistrationCode) { - - return this.codeFragments.generateNewBeanDefinitionCode(generationContext, - beanType, beanRegistrationCode); - - } + CodeBlock generateNewBeanDefinitionCode(GenerationContext generationContext, + ResolvableType beanType, BeanRegistrationCode beanRegistrationCode); /** * Generate the code that sets the properties of the bean definition. @@ -102,14 +74,9 @@ public abstract class BeanRegistrationCodeFragments { * @param attributeFilter any attribute filtering that should be applied * @return the generated code */ - public CodeBlock generateSetBeanDefinitionPropertiesCode( + CodeBlock generateSetBeanDefinitionPropertiesCode( GenerationContext generationContext, BeanRegistrationCode beanRegistrationCode, - RootBeanDefinition beanDefinition, Predicate attributeFilter) { - - return this.codeFragments.generateSetBeanDefinitionPropertiesCode( - generationContext, beanRegistrationCode, beanDefinition, attributeFilter); - - } + RootBeanDefinition beanDefinition, Predicate attributeFilter); /** * Generate the code that sets the instance supplier on the bean definition. @@ -120,13 +87,9 @@ public abstract class BeanRegistrationCodeFragments { * @return the generated code * @see #generateInstanceSupplierCode */ - public CodeBlock generateSetBeanInstanceSupplierCode( + CodeBlock generateSetBeanInstanceSupplierCode( GenerationContext generationContext, BeanRegistrationCode beanRegistrationCode, - CodeBlock instanceSupplierCode, List postProcessors) { - - return this.codeFragments.generateSetBeanInstanceSupplierCode(generationContext, - beanRegistrationCode, instanceSupplierCode, postProcessors); - } + CodeBlock instanceSupplierCode, List postProcessors); /** * Generate the instance supplier code. @@ -138,13 +101,9 @@ public abstract class BeanRegistrationCodeFragments { * than always needing an {@link InstanceSupplier} * @return the generated code */ - public CodeBlock generateInstanceSupplierCode( + CodeBlock generateInstanceSupplierCode( GenerationContext generationContext, BeanRegistrationCode beanRegistrationCode, - Executable constructorOrFactoryMethod, boolean allowDirectSupplierShortcut) { - - return this.codeFragments.generateInstanceSupplierCode(generationContext, - beanRegistrationCode, constructorOrFactoryMethod, allowDirectSupplierShortcut); - } + Executable constructorOrFactoryMethod, boolean allowDirectSupplierShortcut); /** * Generate the return statement. @@ -152,10 +111,7 @@ public abstract class BeanRegistrationCodeFragments { * @param beanRegistrationCode the bean registration code * @return the generated code */ - public CodeBlock generateReturnCode( - GenerationContext generationContext, BeanRegistrationCode beanRegistrationCode) { - - return this.codeFragments.generateReturnCode(generationContext, beanRegistrationCode); - } + CodeBlock generateReturnCode( + GenerationContext generationContext, BeanRegistrationCode beanRegistrationCode); } 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 new file mode 100644 index 00000000000..169e61bc7e0 --- /dev/null +++ b/spring-beans/src/main/java/org/springframework/beans/factory/aot/BeanRegistrationCodeFragmentsDecorator.java @@ -0,0 +1,108 @@ +/* + * Copyright 2002-2022 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. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.beans.factory.aot; + +import java.lang.reflect.Executable; +import java.util.List; +import java.util.function.Predicate; +import java.util.function.UnaryOperator; + +import org.springframework.aot.generate.GenerationContext; +import org.springframework.aot.generate.MethodReference; +import org.springframework.beans.factory.support.RegisteredBean; +import org.springframework.beans.factory.support.RootBeanDefinition; +import org.springframework.core.ResolvableType; +import org.springframework.javapoet.CodeBlock; +import org.springframework.util.Assert; + +/** + * A {@link BeanRegistrationCodeFragments} decorator implementation. Typically + * used when part of the default code fragments have to customized, by extending + * this class and use it as part of + * {@link BeanRegistrationAotContribution#withCustomCodeFragments(UnaryOperator)}. + * + * @author Phillip Webb + * @author Stephane Nicoll + * @since 6.0 + */ +public class BeanRegistrationCodeFragmentsDecorator implements BeanRegistrationCodeFragments { + + + private final BeanRegistrationCodeFragments delegate; + + + protected BeanRegistrationCodeFragmentsDecorator(BeanRegistrationCodeFragments delegate) { + Assert.notNull(delegate, "Delegate must not be null"); + this.delegate = delegate; + } + + @Override + public Class getTarget(RegisteredBean registeredBean, + Executable constructorOrFactoryMethod) { + + return this.delegate.getTarget(registeredBean, constructorOrFactoryMethod); + } + + @Override + public CodeBlock generateNewBeanDefinitionCode(GenerationContext generationContext, + ResolvableType beanType, BeanRegistrationCode beanRegistrationCode) { + + return this.delegate.generateNewBeanDefinitionCode(generationContext, + beanType, beanRegistrationCode); + + } + + @Override + public CodeBlock generateSetBeanDefinitionPropertiesCode( + GenerationContext generationContext, + BeanRegistrationCode beanRegistrationCode, RootBeanDefinition beanDefinition, + Predicate attributeFilter) { + + return this.delegate.generateSetBeanDefinitionPropertiesCode( + generationContext, beanRegistrationCode, beanDefinition, attributeFilter); + + } + + @Override + public CodeBlock generateSetBeanInstanceSupplierCode( + GenerationContext generationContext, + BeanRegistrationCode beanRegistrationCode, CodeBlock instanceSupplierCode, + List postProcessors) { + + return this.delegate.generateSetBeanInstanceSupplierCode(generationContext, + beanRegistrationCode, instanceSupplierCode, postProcessors); + } + + @Override + public CodeBlock generateInstanceSupplierCode(GenerationContext generationContext, + BeanRegistrationCode beanRegistrationCode, + Executable constructorOrFactoryMethod, boolean allowDirectSupplierShortcut) { + + return this.delegate.generateInstanceSupplierCode(generationContext, + beanRegistrationCode, constructorOrFactoryMethod, + allowDirectSupplierShortcut); + } + + @Override + public CodeBlock generateReturnCode(GenerationContext generationContext, + BeanRegistrationCode beanRegistrationCode) { + + return this.delegate.generateReturnCode(generationContext, + beanRegistrationCode); + } + +} diff --git a/spring-beans/src/main/java/org/springframework/beans/factory/aot/DefaultBeanRegistrationCodeFragments.java b/spring-beans/src/main/java/org/springframework/beans/factory/aot/DefaultBeanRegistrationCodeFragments.java index 9a92ecdd34e..0c768629155 100644 --- a/spring-beans/src/main/java/org/springframework/beans/factory/aot/DefaultBeanRegistrationCodeFragments.java +++ b/spring-beans/src/main/java/org/springframework/beans/factory/aot/DefaultBeanRegistrationCodeFragments.java @@ -44,7 +44,7 @@ import org.springframework.util.ClassUtils; * * @author Phillip Webb */ -class DefaultBeanRegistrationCodeFragments extends BeanRegistrationCodeFragments { +class DefaultBeanRegistrationCodeFragments implements BeanRegistrationCodeFragments { /** * The variable name used to hold the bean type. 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 8850a662e5a..46dcb0370e1 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 @@ -196,7 +196,7 @@ class BeanDefinitionMethodGeneratorTests { RegisteredBean registeredBean = registerBean( new RootBeanDefinition(TestBean.class)); BeanRegistrationAotContribution aotContribution = BeanRegistrationAotContribution - .ofBeanRegistrationCodeFragmentsCustomizer(this::customizeBeanDefinitionCode); + .withCustomCodeFragments(this::customizeBeanDefinitionCode); List aotContributions = Collections.singletonList(aotContribution); BeanDefinitionMethodGenerator generator = new BeanDefinitionMethodGenerator( this.methodGeneratorFactory, registeredBean, null, aotContributions); @@ -211,7 +211,7 @@ class BeanDefinitionMethodGeneratorTests { private BeanRegistrationCodeFragments customizeBeanDefinitionCode( BeanRegistrationCodeFragments codeFragments) { - return new BeanRegistrationCodeFragments(codeFragments) { + return new BeanRegistrationCodeFragmentsDecorator(codeFragments) { @Override public CodeBlock generateNewBeanDefinitionCode( @@ -251,7 +251,7 @@ class BeanDefinitionMethodGeneratorTests { beanDefinition.setAttribute("b", "B"); RegisteredBean registeredBean = registerBean(beanDefinition); BeanRegistrationAotContribution aotContribution = BeanRegistrationAotContribution - .ofBeanRegistrationCodeFragmentsCustomizer(this::customizeAttributeFilter); + .withCustomCodeFragments(this::customizeAttributeFilter); List aotContributions = Collections .singletonList(aotContribution); BeanDefinitionMethodGenerator generator = new BeanDefinitionMethodGenerator( @@ -267,7 +267,7 @@ class BeanDefinitionMethodGeneratorTests { private BeanRegistrationCodeFragments customizeAttributeFilter( BeanRegistrationCodeFragments codeFragments) { - return new BeanRegistrationCodeFragments(codeFragments) { + return new BeanRegistrationCodeFragmentsDecorator(codeFragments) { @Override public CodeBlock generateSetBeanDefinitionPropertiesCode( diff --git a/spring-orm/src/main/java/org/springframework/orm/jpa/persistenceunit/PersistenceManagedTypesBeanRegistrationAotProcessor.java b/spring-orm/src/main/java/org/springframework/orm/jpa/persistenceunit/PersistenceManagedTypesBeanRegistrationAotProcessor.java index e8d8fe3848b..5f4a99b4f15 100644 --- a/spring-orm/src/main/java/org/springframework/orm/jpa/persistenceunit/PersistenceManagedTypesBeanRegistrationAotProcessor.java +++ b/spring-orm/src/main/java/org/springframework/orm/jpa/persistenceunit/PersistenceManagedTypesBeanRegistrationAotProcessor.java @@ -34,6 +34,7 @@ import org.springframework.beans.factory.aot.BeanRegistrationAotContribution; import org.springframework.beans.factory.aot.BeanRegistrationAotProcessor; import org.springframework.beans.factory.aot.BeanRegistrationCode; import org.springframework.beans.factory.aot.BeanRegistrationCodeFragments; +import org.springframework.beans.factory.aot.BeanRegistrationCodeFragmentsDecorator; import org.springframework.beans.factory.support.RegisteredBean; import org.springframework.core.annotation.AnnotationUtils; import org.springframework.javapoet.CodeBlock; @@ -58,13 +59,13 @@ class PersistenceManagedTypesBeanRegistrationAotProcessor implements BeanRegistr @Override public BeanRegistrationAotContribution processAheadOfTime(RegisteredBean registeredBean) { if (PersistenceManagedTypes.class.isAssignableFrom(registeredBean.getBeanClass())) { - return BeanRegistrationAotContribution.ofBeanRegistrationCodeFragmentsCustomizer(codeFragments -> + return BeanRegistrationAotContribution.withCustomCodeFragments(codeFragments -> new JpaManagedTypesBeanRegistrationCodeFragments(codeFragments, registeredBean)); } return null; } - private static class JpaManagedTypesBeanRegistrationCodeFragments extends BeanRegistrationCodeFragments { + private static class JpaManagedTypesBeanRegistrationCodeFragments extends BeanRegistrationCodeFragmentsDecorator { private static final ParameterizedTypeName LIST_OF_STRINGS_TYPE = ParameterizedTypeName.get(List.class, String.class);