Browse Source

Revisit BeanRegistrationCodeFragments

This commit revisit BeanRegistrationCodeFragments to separate the
responsibility between the default implementation and the delegates. It
also reviews how customization are applied by improving the Javadoc and
the method name.

Closes gh-28865
pull/29198/head
Stephane Nicoll 4 years ago
parent
commit
c19cedede1
  1. 13
      spring-aop/src/main/java/org/springframework/aop/scope/ScopedProxyBeanRegistrationAotProcessor.java
  2. 22
      spring-beans/src/main/java/org/springframework/beans/factory/aot/BeanRegistrationAotContribution.java
  3. 76
      spring-beans/src/main/java/org/springframework/beans/factory/aot/BeanRegistrationCodeFragments.java
  4. 108
      spring-beans/src/main/java/org/springframework/beans/factory/aot/BeanRegistrationCodeFragmentsDecorator.java
  5. 2
      spring-beans/src/main/java/org/springframework/beans/factory/aot/DefaultBeanRegistrationCodeFragments.java
  6. 8
      spring-beans/src/test/java/org/springframework/beans/factory/aot/BeanDefinitionMethodGeneratorTests.java
  7. 5
      spring-orm/src/main/java/org/springframework/orm/jpa/persistenceunit/PersistenceManagedTypesBeanRegistrationAotProcessor.java

13
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.BeanRegistrationAotProcessor;
import org.springframework.beans.factory.aot.BeanRegistrationCode; import org.springframework.beans.factory.aot.BeanRegistrationCode;
import org.springframework.beans.factory.aot.BeanRegistrationCodeFragments; 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.BeanDefinition;
import org.springframework.beans.factory.config.ConfigurableBeanFactory; import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.beans.factory.support.InstanceSupplier; import org.springframework.beans.factory.support.InstanceSupplier;
@ -63,9 +64,9 @@ class ScopedProxyBeanRegistrationAotProcessor implements BeanRegistrationAotProc
": no target bean definition found with name " + targetBeanName); ": no target bean definition found with name " + targetBeanName);
return null; return null;
} }
return BeanRegistrationAotContribution.ofBeanRegistrationCodeFragmentsCustomizer(codeFragments -> return BeanRegistrationAotContribution.withCustomCodeFragments(codeFragments ->
new ScopedProxyBeanRegistrationCodeFragments(codeFragments, registeredBean, new ScopedProxyBeanRegistrationCodeFragments(codeFragments, registeredBean,
targetBeanName, targetBeanDefinition)); targetBeanName, targetBeanDefinition));
} }
return null; 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"; private static final String REGISTERED_BEAN_PARAMETER_NAME = "registeredBean";
@ -97,10 +98,10 @@ class ScopedProxyBeanRegistrationAotProcessor implements BeanRegistrationAotProc
private final BeanDefinition targetBeanDefinition; private final BeanDefinition targetBeanDefinition;
ScopedProxyBeanRegistrationCodeFragments(BeanRegistrationCodeFragments codeGenerator, ScopedProxyBeanRegistrationCodeFragments(BeanRegistrationCodeFragments delegate,
RegisteredBean registeredBean, String targetBeanName, BeanDefinition targetBeanDefinition) { RegisteredBean registeredBean, String targetBeanName, BeanDefinition targetBeanDefinition) {
super(codeGenerator); super(delegate);
this.registeredBean = registeredBean; this.registeredBean = registeredBean;
this.targetBeanName = targetBeanName; this.targetBeanName = targetBeanName;
this.targetBeanDefinition = targetBeanDefinition; this.targetBeanDefinition = targetBeanDefinition;

22
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. * a single bean definition.
* *
* @author Phillip Webb * @author Phillip Webb
* @author Stephane Nicoll
* @since 6.0 * @since 6.0
* @see BeanRegistrationAotProcessor * @see BeanRegistrationAotProcessor
*/ */
@ -55,24 +56,23 @@ public interface BeanRegistrationAotContribution {
BeanRegistrationCode beanRegistrationCode); BeanRegistrationCode beanRegistrationCode);
/** /**
* Factory method that can be used to create a * Create a {@link BeanRegistrationAotContribution} that customizes
* {@link BeanRegistrationAotContribution} that applies the given * the {@link BeanRegistrationCodeFragments}. Typically used in
* {@link BeanRegistrationCodeFragments} customizer. * conjunction with an extension of {@link BeanRegistrationCodeFragmentsDecorator}
* @param beanRegistrationCodeFragmentsCustomizer the * that overrides a specific callback.
* {@link BeanRegistrationCodeFragments} customizer * @param defaultCodeFragments the default code fragments
* @return a new {@link BeanRegistrationAotContribution} instance * @return a new {@link BeanRegistrationAotContribution} instance
* @see #customizeBeanRegistrationCodeFragments(GenerationContext, BeanRegistrationCodeFragments) * @see BeanRegistrationCodeFragmentsDecorator
*/ */
static BeanRegistrationAotContribution ofBeanRegistrationCodeFragmentsCustomizer( static BeanRegistrationAotContribution withCustomCodeFragments(
UnaryOperator<BeanRegistrationCodeFragments> beanRegistrationCodeFragmentsCustomizer) { UnaryOperator<BeanRegistrationCodeFragments> defaultCodeFragments) {
Assert.notNull(beanRegistrationCodeFragmentsCustomizer, Assert.notNull(defaultCodeFragments, "'defaultCodeFragments' must not be null");
"BeanRegistrationCodeFragmentsCustomizer must not be null");
return new BeanRegistrationAotContribution() { return new BeanRegistrationAotContribution() {
@Override @Override
public BeanRegistrationCodeFragments customizeBeanRegistrationCodeFragments( public BeanRegistrationCodeFragments customizeBeanRegistrationCodeFragments(
GenerationContext generationContext, BeanRegistrationCodeFragments codeFragments) { GenerationContext generationContext, BeanRegistrationCodeFragments codeFragments) {
return beanRegistrationCodeFragmentsCustomizer.apply(codeFragments); return defaultCodeFragments.apply(codeFragments);
} }
@Override @Override

76
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.beans.factory.support.RootBeanDefinition;
import org.springframework.core.ResolvableType; import org.springframework.core.ResolvableType;
import org.springframework.javapoet.CodeBlock; import org.springframework.javapoet.CodeBlock;
import org.springframework.util.Assert;
/** /**
* Class used to generate the various fragments of code needed to register a * Generate the various fragments of code needed to register a bean.
* bean.
* *
* @author Phillip Webb * @author Phillip Webb
* @since 6.0 * @since 6.0
*/ */
public abstract class BeanRegistrationCodeFragments { public interface BeanRegistrationCodeFragments {
/** /**
* The variable name to used when creating the bean definition. * 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. * 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 * Return the target for the registration. Used to determine where to write
* the code. * the code.
@ -74,11 +54,8 @@ public abstract class BeanRegistrationCodeFragments {
* @param constructorOrFactoryMethod the constructor or factory method * @param constructorOrFactoryMethod the constructor or factory method
* @return the target class * @return the target class
*/ */
public Class<?> getTarget(RegisteredBean registeredBean, Class<?> getTarget(RegisteredBean registeredBean,
Executable constructorOrFactoryMethod) { Executable constructorOrFactoryMethod);
return this.codeFragments.getTarget(registeredBean, constructorOrFactoryMethod);
}
/** /**
* Generate the code that defines the new bean definition instance. * Generate the code that defines the new bean definition instance.
@ -87,13 +64,8 @@ public abstract class BeanRegistrationCodeFragments {
* @param beanRegistrationCode the bean registration code * @param beanRegistrationCode the bean registration code
* @return the generated code * @return the generated code
*/ */
public CodeBlock generateNewBeanDefinitionCode(GenerationContext generationContext, CodeBlock generateNewBeanDefinitionCode(GenerationContext generationContext,
ResolvableType beanType, BeanRegistrationCode beanRegistrationCode) { ResolvableType beanType, BeanRegistrationCode beanRegistrationCode);
return this.codeFragments.generateNewBeanDefinitionCode(generationContext,
beanType, beanRegistrationCode);
}
/** /**
* Generate the code that sets the properties of the bean definition. * 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 * @param attributeFilter any attribute filtering that should be applied
* @return the generated code * @return the generated code
*/ */
public CodeBlock generateSetBeanDefinitionPropertiesCode( CodeBlock generateSetBeanDefinitionPropertiesCode(
GenerationContext generationContext, BeanRegistrationCode beanRegistrationCode, GenerationContext generationContext, BeanRegistrationCode beanRegistrationCode,
RootBeanDefinition beanDefinition, Predicate<String> attributeFilter) { RootBeanDefinition beanDefinition, Predicate<String> attributeFilter);
return this.codeFragments.generateSetBeanDefinitionPropertiesCode(
generationContext, beanRegistrationCode, beanDefinition, attributeFilter);
}
/** /**
* Generate the code that sets the instance supplier on the bean definition. * Generate the code that sets the instance supplier on the bean definition.
@ -120,13 +87,9 @@ public abstract class BeanRegistrationCodeFragments {
* @return the generated code * @return the generated code
* @see #generateInstanceSupplierCode * @see #generateInstanceSupplierCode
*/ */
public CodeBlock generateSetBeanInstanceSupplierCode( CodeBlock generateSetBeanInstanceSupplierCode(
GenerationContext generationContext, BeanRegistrationCode beanRegistrationCode, GenerationContext generationContext, BeanRegistrationCode beanRegistrationCode,
CodeBlock instanceSupplierCode, List<MethodReference> postProcessors) { CodeBlock instanceSupplierCode, List<MethodReference> postProcessors);
return this.codeFragments.generateSetBeanInstanceSupplierCode(generationContext,
beanRegistrationCode, instanceSupplierCode, postProcessors);
}
/** /**
* Generate the instance supplier code. * Generate the instance supplier code.
@ -138,13 +101,9 @@ public abstract class BeanRegistrationCodeFragments {
* than always needing an {@link InstanceSupplier} * than always needing an {@link InstanceSupplier}
* @return the generated code * @return the generated code
*/ */
public CodeBlock generateInstanceSupplierCode( CodeBlock generateInstanceSupplierCode(
GenerationContext generationContext, BeanRegistrationCode beanRegistrationCode, GenerationContext generationContext, BeanRegistrationCode beanRegistrationCode,
Executable constructorOrFactoryMethod, boolean allowDirectSupplierShortcut) { Executable constructorOrFactoryMethod, boolean allowDirectSupplierShortcut);
return this.codeFragments.generateInstanceSupplierCode(generationContext,
beanRegistrationCode, constructorOrFactoryMethod, allowDirectSupplierShortcut);
}
/** /**
* Generate the return statement. * Generate the return statement.
@ -152,10 +111,7 @@ public abstract class BeanRegistrationCodeFragments {
* @param beanRegistrationCode the bean registration code * @param beanRegistrationCode the bean registration code
* @return the generated code * @return the generated code
*/ */
public CodeBlock generateReturnCode( CodeBlock generateReturnCode(
GenerationContext generationContext, BeanRegistrationCode beanRegistrationCode) { GenerationContext generationContext, BeanRegistrationCode beanRegistrationCode);
return this.codeFragments.generateReturnCode(generationContext, beanRegistrationCode);
}
} }

108
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<String> attributeFilter) {
return this.delegate.generateSetBeanDefinitionPropertiesCode(
generationContext, beanRegistrationCode, beanDefinition, attributeFilter);
}
@Override
public CodeBlock generateSetBeanInstanceSupplierCode(
GenerationContext generationContext,
BeanRegistrationCode beanRegistrationCode, CodeBlock instanceSupplierCode,
List<MethodReference> 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);
}
}

2
spring-beans/src/main/java/org/springframework/beans/factory/aot/DefaultBeanRegistrationCodeFragments.java

@ -44,7 +44,7 @@ import org.springframework.util.ClassUtils;
* *
* @author Phillip Webb * @author Phillip Webb
*/ */
class DefaultBeanRegistrationCodeFragments extends BeanRegistrationCodeFragments { class DefaultBeanRegistrationCodeFragments implements BeanRegistrationCodeFragments {
/** /**
* The variable name used to hold the bean type. * The variable name used to hold the bean type.

8
spring-beans/src/test/java/org/springframework/beans/factory/aot/BeanDefinitionMethodGeneratorTests.java

@ -196,7 +196,7 @@ class BeanDefinitionMethodGeneratorTests {
RegisteredBean registeredBean = registerBean( RegisteredBean registeredBean = registerBean(
new RootBeanDefinition(TestBean.class)); new RootBeanDefinition(TestBean.class));
BeanRegistrationAotContribution aotContribution = BeanRegistrationAotContribution BeanRegistrationAotContribution aotContribution = BeanRegistrationAotContribution
.ofBeanRegistrationCodeFragmentsCustomizer(this::customizeBeanDefinitionCode); .withCustomCodeFragments(this::customizeBeanDefinitionCode);
List<BeanRegistrationAotContribution> aotContributions = Collections.singletonList(aotContribution); List<BeanRegistrationAotContribution> aotContributions = Collections.singletonList(aotContribution);
BeanDefinitionMethodGenerator generator = new BeanDefinitionMethodGenerator( BeanDefinitionMethodGenerator generator = new BeanDefinitionMethodGenerator(
this.methodGeneratorFactory, registeredBean, null, aotContributions); this.methodGeneratorFactory, registeredBean, null, aotContributions);
@ -211,7 +211,7 @@ class BeanDefinitionMethodGeneratorTests {
private BeanRegistrationCodeFragments customizeBeanDefinitionCode( private BeanRegistrationCodeFragments customizeBeanDefinitionCode(
BeanRegistrationCodeFragments codeFragments) { BeanRegistrationCodeFragments codeFragments) {
return new BeanRegistrationCodeFragments(codeFragments) { return new BeanRegistrationCodeFragmentsDecorator(codeFragments) {
@Override @Override
public CodeBlock generateNewBeanDefinitionCode( public CodeBlock generateNewBeanDefinitionCode(
@ -251,7 +251,7 @@ class BeanDefinitionMethodGeneratorTests {
beanDefinition.setAttribute("b", "B"); beanDefinition.setAttribute("b", "B");
RegisteredBean registeredBean = registerBean(beanDefinition); RegisteredBean registeredBean = registerBean(beanDefinition);
BeanRegistrationAotContribution aotContribution = BeanRegistrationAotContribution BeanRegistrationAotContribution aotContribution = BeanRegistrationAotContribution
.ofBeanRegistrationCodeFragmentsCustomizer(this::customizeAttributeFilter); .withCustomCodeFragments(this::customizeAttributeFilter);
List<BeanRegistrationAotContribution> aotContributions = Collections List<BeanRegistrationAotContribution> aotContributions = Collections
.singletonList(aotContribution); .singletonList(aotContribution);
BeanDefinitionMethodGenerator generator = new BeanDefinitionMethodGenerator( BeanDefinitionMethodGenerator generator = new BeanDefinitionMethodGenerator(
@ -267,7 +267,7 @@ class BeanDefinitionMethodGeneratorTests {
private BeanRegistrationCodeFragments customizeAttributeFilter( private BeanRegistrationCodeFragments customizeAttributeFilter(
BeanRegistrationCodeFragments codeFragments) { BeanRegistrationCodeFragments codeFragments) {
return new BeanRegistrationCodeFragments(codeFragments) { return new BeanRegistrationCodeFragmentsDecorator(codeFragments) {
@Override @Override
public CodeBlock generateSetBeanDefinitionPropertiesCode( public CodeBlock generateSetBeanDefinitionPropertiesCode(

5
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.BeanRegistrationAotProcessor;
import org.springframework.beans.factory.aot.BeanRegistrationCode; import org.springframework.beans.factory.aot.BeanRegistrationCode;
import org.springframework.beans.factory.aot.BeanRegistrationCodeFragments; import org.springframework.beans.factory.aot.BeanRegistrationCodeFragments;
import org.springframework.beans.factory.aot.BeanRegistrationCodeFragmentsDecorator;
import org.springframework.beans.factory.support.RegisteredBean; import org.springframework.beans.factory.support.RegisteredBean;
import org.springframework.core.annotation.AnnotationUtils; import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.javapoet.CodeBlock; import org.springframework.javapoet.CodeBlock;
@ -58,13 +59,13 @@ class PersistenceManagedTypesBeanRegistrationAotProcessor implements BeanRegistr
@Override @Override
public BeanRegistrationAotContribution processAheadOfTime(RegisteredBean registeredBean) { public BeanRegistrationAotContribution processAheadOfTime(RegisteredBean registeredBean) {
if (PersistenceManagedTypes.class.isAssignableFrom(registeredBean.getBeanClass())) { if (PersistenceManagedTypes.class.isAssignableFrom(registeredBean.getBeanClass())) {
return BeanRegistrationAotContribution.ofBeanRegistrationCodeFragmentsCustomizer(codeFragments -> return BeanRegistrationAotContribution.withCustomCodeFragments(codeFragments ->
new JpaManagedTypesBeanRegistrationCodeFragments(codeFragments, registeredBean)); new JpaManagedTypesBeanRegistrationCodeFragments(codeFragments, registeredBean));
} }
return null; 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); private static final ParameterizedTypeName LIST_OF_STRINGS_TYPE = ParameterizedTypeName.get(List.class, String.class);

Loading…
Cancel
Save