Rename BeanInstantiationContributor to Contribution
This commit polishes the contribution model where an AOT contributing bean post processor can return a contribution, rather than a contributor. This makes it easier to return `null` if no contribution can be produced now that it is named this way. See gh-28047
This commit is contained in:
parent
572d017370
commit
20b17f02a2
|
@ -57,7 +57,7 @@ import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
|
|||
import org.springframework.beans.factory.config.DependencyDescriptor;
|
||||
import org.springframework.beans.factory.config.SmartInstantiationAwareBeanPostProcessor;
|
||||
import org.springframework.beans.factory.generator.AotContributingBeanPostProcessor;
|
||||
import org.springframework.beans.factory.generator.BeanInstantiationContributor;
|
||||
import org.springframework.beans.factory.generator.BeanInstantiationContribution;
|
||||
import org.springframework.beans.factory.generator.InjectionGenerator;
|
||||
import org.springframework.beans.factory.support.LookupOverride;
|
||||
import org.springframework.beans.factory.support.MergedBeanDefinitionPostProcessor;
|
||||
|
@ -268,12 +268,12 @@ public class AutowiredAnnotationBeanPostProcessor implements SmartInstantiationA
|
|||
}
|
||||
|
||||
@Override
|
||||
public BeanInstantiationContributor buildAotContributor(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {
|
||||
public BeanInstantiationContribution contribute(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {
|
||||
InjectionMetadata metadata = findInjectionMetadata(beanName, beanType, beanDefinition);
|
||||
Collection<InjectedElement> injectedElements = metadata.getInjectedElements();
|
||||
return (!ObjectUtils.isEmpty(injectedElements)
|
||||
? new AutowiredAnnotationBeanInstantiationContributor(injectedElements)
|
||||
: BeanInstantiationContributor.NO_OP);
|
||||
? new AutowiredAnnotationBeanInstantiationContribution(injectedElements)
|
||||
: null);
|
||||
}
|
||||
|
||||
private InjectionMetadata findInjectionMetadata(String beanName, Class<?> beanType, RootBeanDefinition beanDefinition) {
|
||||
|
@ -821,19 +821,19 @@ public class AutowiredAnnotationBeanPostProcessor implements SmartInstantiationA
|
|||
}
|
||||
}
|
||||
|
||||
private static final class AutowiredAnnotationBeanInstantiationContributor implements BeanInstantiationContributor {
|
||||
private static final class AutowiredAnnotationBeanInstantiationContribution implements BeanInstantiationContribution {
|
||||
|
||||
private final Collection<InjectedElement> injectedElements;
|
||||
|
||||
private final InjectionGenerator generator;
|
||||
|
||||
AutowiredAnnotationBeanInstantiationContributor(Collection<InjectedElement> injectedElements) {
|
||||
AutowiredAnnotationBeanInstantiationContribution(Collection<InjectedElement> injectedElements) {
|
||||
this.injectedElements = injectedElements;
|
||||
this.generator = new InjectionGenerator();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void contribute(CodeContribution contribution) {
|
||||
public void applyTo(CodeContribution contribution) {
|
||||
this.injectedElements.forEach(element -> {
|
||||
boolean isRequired = isRequired(element);
|
||||
Member member = element.getMember();
|
||||
|
|
|
@ -18,6 +18,7 @@ package org.springframework.beans.factory.generator;
|
|||
|
||||
import org.springframework.beans.factory.config.BeanPostProcessor;
|
||||
import org.springframework.beans.factory.support.RootBeanDefinition;
|
||||
import org.springframework.lang.Nullable;
|
||||
|
||||
/**
|
||||
* Specialization of {@link BeanPostProcessor} that contributes to bean
|
||||
|
@ -35,12 +36,14 @@ import org.springframework.beans.factory.support.RootBeanDefinition;
|
|||
public interface AotContributingBeanPostProcessor extends BeanPostProcessor {
|
||||
|
||||
/**
|
||||
* Build a {@link BeanInstantiationContributor} for the given bean definition.
|
||||
* Contribute a {@link BeanInstantiationContribution} for the given bean definition,
|
||||
* if applicable.
|
||||
* @param beanDefinition the merged bean definition for the bean
|
||||
* @param beanType the inferred type of the bean
|
||||
* @param beanName the name of the bean
|
||||
* @return the contributor to use
|
||||
* @return the contribution to use or {@code null} if the bean should not be processed
|
||||
*/
|
||||
BeanInstantiationContributor buildAotContributor(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName);
|
||||
@Nullable
|
||||
BeanInstantiationContribution contribute(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName);
|
||||
|
||||
}
|
||||
|
|
|
@ -19,24 +19,18 @@ package org.springframework.beans.factory.generator;
|
|||
import org.springframework.aot.generator.CodeContribution;
|
||||
|
||||
/**
|
||||
* Contributor to the code that instantiates a bean following ahead of time
|
||||
* A contribution to the instantiation of a bean following ahead of time
|
||||
* processing.
|
||||
*
|
||||
* @author Stephane Nicoll
|
||||
* @since 6.0
|
||||
*/
|
||||
@FunctionalInterface
|
||||
public interface BeanInstantiationContributor {
|
||||
public interface BeanInstantiationContribution {
|
||||
|
||||
/**
|
||||
* A {@link BeanInstantiationContributor} that does not contribute anything
|
||||
* to the {@link CodeContribution}.
|
||||
*/
|
||||
BeanInstantiationContributor NO_OP = contribution -> { };
|
||||
|
||||
/**
|
||||
* Contribute to the specified {@link CodeContribution}.
|
||||
* <p>Implementation of this interface can assume the following variables
|
||||
* Contribute bean instantiation to the specified {@link CodeContribution}.
|
||||
* <p>Implementations of this interface can assume the following variables
|
||||
* to be accessible:
|
||||
* <ul>
|
||||
* <li>{@code beanFactory}: the general {@code DefaultListableBeanFactory}</li>
|
||||
|
@ -45,6 +39,6 @@ public interface BeanInstantiationContributor {
|
|||
* </ul>
|
||||
* @param contribution the {@link CodeContribution} to use
|
||||
*/
|
||||
void contribute(CodeContribution contribution);
|
||||
void applyTo(CodeContribution contribution);
|
||||
|
||||
}
|
|
@ -36,25 +36,25 @@ import org.springframework.util.ClassUtils;
|
|||
* Write the necessary statements to instantiate a bean.
|
||||
*
|
||||
* @author Stephane Nicoll
|
||||
* @see BeanInstantiationContributor
|
||||
* @see BeanInstantiationContribution
|
||||
*/
|
||||
class DefaultBeanInstantiationGenerator {
|
||||
|
||||
private final Executable instanceCreator;
|
||||
|
||||
private final List<BeanInstantiationContributor> contributors;
|
||||
private final List<BeanInstantiationContribution> contributions;
|
||||
|
||||
private final InjectionGenerator injectionGenerator;
|
||||
|
||||
private final Options beanInstanceOptions;
|
||||
|
||||
|
||||
DefaultBeanInstantiationGenerator(Executable instanceCreator, List<BeanInstantiationContributor> contributors) {
|
||||
DefaultBeanInstantiationGenerator(Executable instanceCreator, List<BeanInstantiationContribution> contributions) {
|
||||
this.instanceCreator = instanceCreator;
|
||||
this.contributors = List.copyOf(contributors);
|
||||
this.contributions = List.copyOf(contributions);
|
||||
this.injectionGenerator = new InjectionGenerator();
|
||||
this.beanInstanceOptions = Options.defaults().useReflection(member -> false)
|
||||
.assignReturnType(member -> !this.contributors.isEmpty()).build();
|
||||
.assignReturnType(member -> !this.contributions.isEmpty()).build();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -78,7 +78,7 @@ class DefaultBeanInstantiationGenerator {
|
|||
private void writeBeanInstantiation(CodeContribution contribution, Constructor<?> constructor) {
|
||||
Class<?> declaringType = ClassUtils.getUserClass(constructor.getDeclaringClass());
|
||||
boolean innerClass = isInnerClass(declaringType);
|
||||
boolean multiStatements = !this.contributors.isEmpty();
|
||||
boolean multiStatements = !this.contributions.isEmpty();
|
||||
int minArgs = isInnerClass(declaringType) ? 2 : 1;
|
||||
CodeBlock.Builder code = CodeBlock.builder();
|
||||
// Shortcut for common case
|
||||
|
@ -110,8 +110,8 @@ class DefaultBeanInstantiationGenerator {
|
|||
contribution.statements().addStatement(code.build());
|
||||
|
||||
if (multiStatements) {
|
||||
for (BeanInstantiationContributor contributor : this.contributors) {
|
||||
contributor.contribute(contribution);
|
||||
for (BeanInstantiationContribution contributor : this.contributions) {
|
||||
contributor.applyTo(contribution);
|
||||
}
|
||||
contribution.statements().addStatement("return bean")
|
||||
.add(codeBlock -> codeBlock.unindent().add("}"));
|
||||
|
@ -127,7 +127,7 @@ class DefaultBeanInstantiationGenerator {
|
|||
contribution.runtimeHints().reflection().registerMethod(method,
|
||||
hint -> hint.withMode(ExecutableMode.INTROSPECT));
|
||||
List<Class<?>> parameterTypes = new ArrayList<>(Arrays.asList(method.getParameterTypes()));
|
||||
boolean multiStatements = !this.contributors.isEmpty();
|
||||
boolean multiStatements = !this.contributions.isEmpty();
|
||||
Class<?> declaringType = method.getDeclaringClass();
|
||||
CodeBlock.Builder code = CodeBlock.builder();
|
||||
// Shortcut for common case
|
||||
|
@ -148,8 +148,8 @@ class DefaultBeanInstantiationGenerator {
|
|||
code.add(this.injectionGenerator.writeInstantiation(method));
|
||||
contribution.statements().addStatement(code.build());
|
||||
if (multiStatements) {
|
||||
for (BeanInstantiationContributor contributor : this.contributors) {
|
||||
contributor.contribute(contribution);
|
||||
for (BeanInstantiationContribution contributor : this.contributions) {
|
||||
contributor.applyTo(contribution);
|
||||
}
|
||||
contribution.statements().addStatement("return bean")
|
||||
.add(codeBlock -> codeBlock.unindent().add("}"));
|
||||
|
|
|
@ -24,11 +24,12 @@ import org.springframework.aot.hint.ExecutableMode;
|
|||
import org.springframework.aot.hint.RuntimeHints;
|
||||
import org.springframework.aot.hint.TypeReference;
|
||||
import org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessorTests.ResourceInjectionBean;
|
||||
import org.springframework.beans.factory.generator.BeanInstantiationContributor;
|
||||
import org.springframework.beans.factory.generator.BeanInstantiationContribution;
|
||||
import org.springframework.beans.factory.support.RootBeanDefinition;
|
||||
import org.springframework.beans.testfixture.beans.TestBean;
|
||||
import org.springframework.core.env.Environment;
|
||||
import org.springframework.javapoet.support.CodeSnippet;
|
||||
import org.springframework.lang.Nullable;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
|
@ -37,10 +38,10 @@ import static org.assertj.core.api.Assertions.assertThat;
|
|||
*
|
||||
* @author Stephane Nicoll
|
||||
*/
|
||||
class AutowiredAnnotationBeanInstantiationContributorTests {
|
||||
class AutowiredAnnotationBeanInstantiationContributionTests {
|
||||
|
||||
@Test
|
||||
void buildAotContributorWithPackageProtectedFieldInjection() {
|
||||
void contributeWithPackageProtectedFieldInjection() {
|
||||
CodeContribution contribution = contribute(PackageProtectedFieldInjectionSample.class);
|
||||
assertThat(CodeSnippet.process(contribution.statements().toCodeBlock())).isEqualTo("""
|
||||
instanceContext.field("environment", Environment.class)
|
||||
|
@ -58,12 +59,12 @@ class AutowiredAnnotationBeanInstantiationContributorTests {
|
|||
}
|
||||
|
||||
@Test
|
||||
void buildAotContributorWithPrivateFieldInjection() {
|
||||
void contributeWithPrivateFieldInjection() {
|
||||
CodeContribution contribution = contribute(PrivateFieldInjectionSample.class);
|
||||
assertThat(CodeSnippet.process(contribution.statements().toCodeBlock())).isEqualTo("""
|
||||
instanceContext.field("environment", Environment.class)
|
||||
.invoke(beanFactory, (attributes) -> {
|
||||
Field environmentField = ReflectionUtils.findField(AutowiredAnnotationBeanInstantiationContributorTests.PrivateFieldInjectionSample.class, "environment", Environment.class);
|
||||
Field environmentField = ReflectionUtils.findField(AutowiredAnnotationBeanInstantiationContributionTests.PrivateFieldInjectionSample.class, "environment", Environment.class);
|
||||
ReflectionUtils.makeAccessible(environmentField);
|
||||
ReflectionUtils.setField(environmentField, bean, attributes.get(0));
|
||||
})""");
|
||||
|
@ -79,7 +80,7 @@ class AutowiredAnnotationBeanInstantiationContributorTests {
|
|||
}
|
||||
|
||||
@Test
|
||||
void buildAotContributorWithPublicMethodInjection() {
|
||||
void contributeWithPublicMethodInjection() {
|
||||
CodeContribution contribution = contribute(PublicMethodInjectionSample.class);
|
||||
assertThat(CodeSnippet.process(contribution.statements().toCodeBlock())).isEqualTo("""
|
||||
instanceContext.method("setTestBean", TestBean.class)
|
||||
|
@ -95,7 +96,7 @@ class AutowiredAnnotationBeanInstantiationContributorTests {
|
|||
}
|
||||
|
||||
@Test
|
||||
void buildAotContributorWithInjectionPoints() {
|
||||
void contributeWithInjectionPoints() {
|
||||
CodeContribution contribution = contribute(ResourceInjectionBean.class);
|
||||
assertThat(CodeSnippet.process(contribution.statements().toCodeBlock())).isEqualTo("""
|
||||
instanceContext.field("testBean", TestBean.class)
|
||||
|
@ -116,23 +117,24 @@ class AutowiredAnnotationBeanInstantiationContributorTests {
|
|||
}
|
||||
|
||||
@Test
|
||||
void buildAotContributorWithoutInjectionPoints() {
|
||||
BeanInstantiationContributor contributor = createAotContributor(String.class);
|
||||
assertThat(contributor).isNotNull().isSameAs(BeanInstantiationContributor.NO_OP);
|
||||
void contributeWithoutInjectionPoints() {
|
||||
BeanInstantiationContribution contributor = createContribution(String.class);
|
||||
assertThat(contributor).isNull();
|
||||
}
|
||||
|
||||
private DefaultCodeContribution contribute(Class<?> type) {
|
||||
BeanInstantiationContributor contributor = createAotContributor(type);
|
||||
BeanInstantiationContribution contributor = createContribution(type);
|
||||
assertThat(contributor).isNotNull();
|
||||
DefaultCodeContribution contribution = new DefaultCodeContribution(new RuntimeHints());
|
||||
contributor.contribute(contribution);
|
||||
contributor.applyTo(contribution);
|
||||
return contribution;
|
||||
}
|
||||
|
||||
private BeanInstantiationContributor createAotContributor(Class<?> type) {
|
||||
@Nullable
|
||||
private BeanInstantiationContribution createContribution(Class<?> type) {
|
||||
AutowiredAnnotationBeanPostProcessor bpp = new AutowiredAnnotationBeanPostProcessor();
|
||||
RootBeanDefinition beanDefinition = new RootBeanDefinition(type);
|
||||
return bpp.buildAotContributor(beanDefinition, type, "test");
|
||||
return bpp.contribute(beanDefinition, type, "test");
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -106,10 +106,10 @@ class DefaultBeanInstantiationGeneratorTests {
|
|||
}
|
||||
|
||||
@Test
|
||||
void generateUsingNoArgConstructorAndContributorsDoesNotUseMethodReference() {
|
||||
void generateUsingNoArgConstructorAndContributionsDoesNotUseMethodReference() {
|
||||
CodeContribution contribution = generate(SimpleConfiguration.class.getDeclaredConstructors()[0],
|
||||
contrib -> contrib.statements().add(CodeBlock.of("// hello\n")),
|
||||
BeanInstantiationContributor.NO_OP);
|
||||
contrib -> {});
|
||||
assertThat(code(contribution)).isEqualTo("""
|
||||
(instanceContext) -> {
|
||||
SimpleConfiguration bean = new SimpleConfiguration();
|
||||
|
@ -119,7 +119,7 @@ class DefaultBeanInstantiationGeneratorTests {
|
|||
}
|
||||
|
||||
@Test
|
||||
void generateUsingContributorsRegisterHints() {
|
||||
void generateUsingContributionsRegisterHints() {
|
||||
CodeContribution contribution = generate(SimpleConfiguration.class.getDeclaredConstructors()[0],
|
||||
contrib -> {
|
||||
contrib.statements().add(CodeBlock.of("// hello\n"));
|
||||
|
@ -170,7 +170,7 @@ class DefaultBeanInstantiationGeneratorTests {
|
|||
}
|
||||
|
||||
@Test
|
||||
void generateUsingMethodAndContributors() {
|
||||
void generateUsingMethodAndContributions() {
|
||||
CodeContribution contribution = generate(method(SimpleConfiguration.class, "stringBean"),
|
||||
contrib -> {
|
||||
contrib.statements().add(CodeBlock.of("// hello\n"));
|
||||
|
@ -240,9 +240,9 @@ class DefaultBeanInstantiationGeneratorTests {
|
|||
}
|
||||
|
||||
private CodeContribution generate(Executable executable,
|
||||
BeanInstantiationContributor... beanInstantiationContributors) {
|
||||
BeanInstantiationContribution... beanInstantiationContributions) {
|
||||
DefaultBeanInstantiationGenerator generator = new DefaultBeanInstantiationGenerator(executable,
|
||||
Arrays.asList(beanInstantiationContributors));
|
||||
Arrays.asList(beanInstantiationContributions));
|
||||
return generator.generateBeanInstantiation(new RuntimeHints());
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue