Skip to content
This repository was archived by the owner on Feb 23, 2023. It is now read-only.

Commit c603e0c

Browse files
committed
Align callback order with regular runtime
This commit moves handling of ImportAware in a bean post processor to match the ordering of the regular runtime. As a result, bean instance descriptor does not have to know about instance callbacks. Closes gh-1014
1 parent 1d055a1 commit c603e0c

File tree

12 files changed

+133
-380
lines changed

12 files changed

+133
-380
lines changed

spring-aot/src/main/java/org/springframework/context/bootstrap/generator/bean/DefaultBeanInstanceSupplierWriter.java

+2-11
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,6 @@
2828

2929
import org.springframework.beans.factory.config.BeanDefinition;
3030
import org.springframework.context.bootstrap.generator.bean.descriptor.BeanInstanceDescriptor;
31-
import org.springframework.context.bootstrap.generator.bean.descriptor.BeanInstanceDescriptor.InstanceCallback;
3231
import org.springframework.context.bootstrap.generator.bean.descriptor.BeanInstanceDescriptor.MemberDescriptor;
3332
import org.springframework.util.ClassUtils;
3433

@@ -72,8 +71,7 @@ private void writeBeanInstantiation(Builder code, Constructor<?> constructor) {
7271
if (innerClass) { // Remove the implicit argument
7372
parameterTypes.remove(0);
7473
}
75-
boolean multiStatements = !this.descriptor.getInstanceCallbacks().isEmpty() ||
76-
!this.descriptor.getInjectionPoints().isEmpty();
74+
boolean multiStatements = !this.descriptor.getInjectionPoints().isEmpty();
7775
int minArgs = isInnerClass(declaringType) ? 2 : 1;
7876
// Shortcut for common case
7977
if (!multiStatements && constructor.getParameterTypes().length < minArgs) {
@@ -94,9 +92,6 @@ private void writeBeanInstantiation(Builder code, Constructor<?> constructor) {
9492
if (multiStatements) {
9593
code.add(";\n");
9694
}
97-
for (InstanceCallback instanceCallback : this.descriptor.getInstanceCallbacks()) {
98-
code.addStatement(instanceCallback.write("bean"));
99-
}
10095
for (MemberDescriptor<?> injectionPoint : this.descriptor.getInjectionPoints()) {
10196
code.add(this.injectionPointWriter.writeInjection(injectionPoint.getMember(), injectionPoint.isRequired())).add(";\n");
10297
}
@@ -112,8 +107,7 @@ private static boolean isInnerClass(Class<?> type) {
112107

113108
private void writeBeanInstantiation(Builder code, Method method) {
114109
List<Class<?>> parameterTypes = new ArrayList<>(Arrays.asList(method.getParameterTypes()));
115-
boolean multiStatements = !this.descriptor.getInstanceCallbacks().isEmpty() ||
116-
!this.descriptor.getInjectionPoints().isEmpty();
110+
boolean multiStatements = !this.descriptor.getInjectionPoints().isEmpty();
117111
Class<?> declaringType = method.getDeclaringClass();
118112
// Shortcut for common case
119113
if (!multiStatements && parameterTypes.isEmpty()) {
@@ -133,9 +127,6 @@ private void writeBeanInstantiation(Builder code, Method method) {
133127
if (multiStatements) {
134128
code.add(";\n");
135129
}
136-
for (InstanceCallback instanceCallback : this.descriptor.getInstanceCallbacks()) {
137-
code.addStatement(instanceCallback.write("bean"));
138-
}
139130
for (MemberDescriptor<?> injectionPoint : this.descriptor.getInjectionPoints()) {
140131
code.add(this.injectionPointWriter.writeInjection(injectionPoint.getMember(), injectionPoint.isRequired())).add(";\n");
141132
}

spring-aot/src/main/java/org/springframework/context/bootstrap/generator/bean/descriptor/BeanInstanceDescriptor.java

-40
Original file line numberDiff line numberDiff line change
@@ -41,16 +41,13 @@ public final class BeanInstanceDescriptor {
4141

4242
private final MemberDescriptor<Executable> instanceCreator;
4343

44-
private final List<InstanceCallback> instanceCallbacks;
45-
4644
private final List<MemberDescriptor<?>> injectionPoints;
4745

4846
private final List<PropertyDescriptor> properties;
4947

5048
private BeanInstanceDescriptor(Builder builder) {
5149
this.beanType = builder.beanType;
5250
this.instanceCreator = builder.instanceCreator;
53-
this.instanceCallbacks = new ArrayList<>(builder.instanceCallbacks);
5451
this.injectionPoints = new ArrayList<>(builder.injectionPoints);
5552
this.properties = new ArrayList<>(builder.properties);
5653
}
@@ -98,15 +95,6 @@ public MemberDescriptor<Executable> getInstanceCreator() {
9895
return this.instanceCreator;
9996
}
10097

101-
/**
102-
* Return the callbacks that should be honored after the instance is created but
103-
* before injection points apply.
104-
* @return the instance callbacks, if any.
105-
*/
106-
public List<InstanceCallback> getInstanceCallbacks() {
107-
return this.instanceCallbacks;
108-
}
109-
11098
/**
11199
* Return the injection points to invoke to populate extra dependencies for the bean,
112100
* in the order they should be invoked.
@@ -150,22 +138,6 @@ public boolean isRequired() {
150138

151139
}
152140

153-
/**
154-
* Wraps the code that's necessary to honor instance callbacks if any.
155-
*/
156-
public static class InstanceCallback {
157-
158-
private final Function<String, CodeBlock> code;
159-
160-
public InstanceCallback(Function<String, CodeBlock> code) {
161-
this.code = code;
162-
}
163-
164-
public CodeBlock write(String beanVariable) {
165-
return this.code.apply(beanVariable);
166-
}
167-
}
168-
169141
/**
170142
* Describe a property that is used to initialize a Bean instance.
171143
*/
@@ -196,8 +168,6 @@ public static class Builder {
196168

197169
private MemberDescriptor<Executable> instanceCreator;
198170

199-
private final List<InstanceCallback> instanceCallbacks = new ArrayList<>();
200-
201171
private final List<MemberDescriptor<?>> injectionPoints = new ArrayList<>();
202172

203173
private final List<PropertyDescriptor> properties = new ArrayList<>();
@@ -212,16 +182,6 @@ public Builder withInstanceCreator(Executable executable) {
212182
return this;
213183
}
214184

215-
public Builder withInstanceCallback(Function<String, CodeBlock> code) {
216-
this.instanceCallbacks.add(new InstanceCallback(code));
217-
return this;
218-
}
219-
220-
public Builder withInstanceCallbacks(List<InstanceCallback> instanceCallbacks) {
221-
this.instanceCallbacks.addAll(instanceCallbacks);
222-
return this;
223-
}
224-
225185
public Builder withInjectionPoint(Member member, boolean required) {
226186
this.injectionPoints.add(new MemberDescriptor<>(member, required));
227187
return this;

spring-aot/src/main/java/org/springframework/context/bootstrap/generator/bean/descriptor/DefaultBeanInstanceDescriptorFactory.java

+2-7
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@
2121

2222
import org.springframework.beans.factory.config.BeanDefinition;
2323
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
24-
import org.springframework.context.bootstrap.generator.bean.descriptor.BeanInstanceDescriptor.InstanceCallback;
2524
import org.springframework.context.bootstrap.generator.bean.descriptor.BeanInstanceDescriptor.MemberDescriptor;
2625
import org.springframework.context.bootstrap.generator.bean.descriptor.BeanInstanceDescriptor.PropertyDescriptor;
2726
import org.springframework.util.Assert;
@@ -36,15 +35,12 @@ public class DefaultBeanInstanceDescriptorFactory implements BeanInstanceDescrip
3635

3736
private final BeanInstanceExecutableSupplier instanceCreatorSupplier;
3837

39-
private final InstanceCallbacksSupplier instanceCallbacksSupplier;
40-
4138
private final InjectionPointsSupplier injectionPointsSupplier;
4239

4340
private final PropertiesSupplier propertiesSupplier;
4441

4542
public DefaultBeanInstanceDescriptorFactory(ConfigurableBeanFactory beanFactory) {
4643
this.instanceCreatorSupplier = new BeanInstanceExecutableSupplier(beanFactory);
47-
this.instanceCallbacksSupplier = new InstanceCallbacksSupplier();
4844
this.injectionPointsSupplier = new InjectionPointsSupplier(beanFactory.getBeanClassLoader());
4945
this.propertiesSupplier = new PropertiesSupplier();
5046
}
@@ -55,12 +51,11 @@ public BeanInstanceDescriptor create(BeanDefinition beanDefinition) {
5551
Executable instanceCreator = this.instanceCreatorSupplier.detectBeanInstanceExecutable(beanDefinition);
5652
if (instanceCreator != null) {
5753
Class<?> beanType = beanDefinition.getResolvableType().toClass();
58-
List<InstanceCallback> instanceCallbacks = this.instanceCallbacksSupplier.detectInstanceCallbacks(beanType);
5954
List<MemberDescriptor<?>> injectionPoints = this.injectionPointsSupplier.detectInjectionPoints(beanType);
6055
List<PropertyDescriptor> properties = this.propertiesSupplier.detectProperties(beanDefinition);
6156
return BeanInstanceDescriptor.of(beanDefinition.getResolvableType())
62-
.withInstanceCreator(instanceCreator).withInstanceCallbacks(instanceCallbacks)
63-
.withInjectionPoints(injectionPoints).withProperties(properties).build();
57+
.withInstanceCreator(instanceCreator).withInjectionPoints(injectionPoints)
58+
.withProperties(properties).build();
6459
}
6560
return null;
6661
}

spring-aot/src/main/java/org/springframework/context/bootstrap/generator/bean/descriptor/InstanceCallbacksSupplier.java

-49
This file was deleted.

spring-aot/src/main/java/org/springframework/context/bootstrap/generator/infrastructure/BootstrapInfrastructureWriter.java

+9-9
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@
3030
import com.squareup.javapoet.MethodSpec;
3131
import com.squareup.javapoet.ParameterizedTypeName;
3232

33-
import org.springframework.aot.context.annotation.ImportAwareInvoker;
33+
import org.springframework.aot.context.annotation.ImportAwareBeanPostProcessor;
3434
import org.springframework.aot.context.annotation.InitDestroyBeanPostProcessor;
3535
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
3636
import org.springframework.context.annotation.ContextAnnotationAutowireCandidateResolver;
@@ -63,10 +63,10 @@ public BootstrapInfrastructureWriter(ConfigurableListableBeanFactory beanFactory
6363
public void writeInfrastructure(CodeBlock.Builder code) {
6464
code.addStatement("context.getDefaultListableBeanFactory().setAutowireCandidateResolver(new $T())",
6565
ContextAnnotationAutowireCandidateResolver.class);
66-
MethodSpec importAwareInvokerMethod = handleImportAwareInvoker();
67-
if (importAwareInvokerMethod != null) {
68-
this.writerContext.getBootstrapClass(this.writerContext.getPackageName()).addMethod(importAwareInvokerMethod);
69-
code.addStatement("$T.register(context, this::createImportAwareInvoker)", ImportAwareInvoker.class);
66+
MethodSpec importAwareBeanPostProcessorMethod = handleImportAwareBeanPostProcessor();
67+
if (importAwareBeanPostProcessorMethod != null) {
68+
this.writerContext.getBootstrapClass(this.writerContext.getPackageName()).addMethod(importAwareBeanPostProcessorMethod);
69+
code.addStatement("context.getBeanFactory().addBeanPostProcessor($N())", importAwareBeanPostProcessorMethod);
7070
}
7171
MethodSpec initDestroyBeanPostProcessorMethod = handleInitDestroyBeanPostProcessor();
7272
if (initDestroyBeanPostProcessorMethod != null) {
@@ -75,9 +75,9 @@ public void writeInfrastructure(CodeBlock.Builder code) {
7575
}
7676
}
7777

78-
private MethodSpec handleImportAwareInvoker() {
78+
private MethodSpec handleImportAwareBeanPostProcessor() {
7979
ImportOriginRegistry importOriginRegistry = ImportOriginRegistry.get(this.beanFactory);
80-
if (importOriginRegistry == null) {
80+
if (importOriginRegistry == null || importOriginRegistry.getImportOrigins().isEmpty()) {
8181
return null;
8282
}
8383
Map<String, Class<?>> importLinks = importOriginRegistry.getImportOrigins();
@@ -91,8 +91,8 @@ private MethodSpec handleImportAwareInvoker() {
9191
importLinks.forEach((key, value) -> {
9292
code.addStatement("mappings.put($S, $S)", key, value.getName());
9393
});
94-
code.addStatement("return new $T($L)", ImportAwareInvoker.class, "mappings");
95-
return MethodSpec.methodBuilder("createImportAwareInvoker").returns(ImportAwareInvoker.class)
94+
code.addStatement("return new $T($L)", ImportAwareBeanPostProcessor.class, "mappings");
95+
return MethodSpec.methodBuilder("createImportAwareBeanPostProcessor").returns(ImportAwareBeanPostProcessor.class)
9696
.addModifiers(Modifier.PRIVATE).addCode(code.build()).build();
9797
}
9898

spring-aot/src/test/java/org/springframework/context/bootstrap/generator/bean/DefaultBeanInstanceSupplierWriterTests.java

-46
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@
2222
import java.util.Arrays;
2323
import java.util.function.Function;
2424

25-
import com.squareup.javapoet.CodeBlock;
2625
import org.junit.jupiter.api.Test;
2726

2827
import org.springframework.beans.factory.config.BeanDefinition;
@@ -33,7 +32,6 @@
3332
import org.springframework.context.bootstrap.generator.sample.InnerComponentConfiguration.EnvironmentAwareComponent;
3433
import org.springframework.context.bootstrap.generator.sample.InnerComponentConfiguration.NoDependencyComponent;
3534
import org.springframework.context.bootstrap.generator.sample.SimpleConfiguration;
36-
import org.springframework.context.bootstrap.generator.sample.callback.ImportAwareConfiguration;
3735
import org.springframework.context.bootstrap.generator.sample.factory.NumberHolder;
3836
import org.springframework.context.bootstrap.generator.sample.factory.NumberHolderFactoryBean;
3937
import org.springframework.context.bootstrap.generator.sample.factory.SampleFactory;
@@ -99,34 +97,6 @@ void writeConstructorForFactoryBean() {
9997
).isEqualTo("() -> new NumberHolderFactoryBean()").hasImport(NumberHolderFactoryBean.class);
10098
}
10199

102-
@Test
103-
void writeConstructorWithInstanceCallback() {
104-
BeanDefinition beanDefinition = BeanDefinitionBuilder.rootBeanDefinition(ImportAwareConfiguration.class).getBeanDefinition();
105-
assertThat(generateCode(beanDefinition, (type) -> BeanInstanceDescriptor.of(type)
106-
.withInstanceCreator(ImportAwareConfiguration.class.getDeclaredConstructors()[0])
107-
.withInstanceCallback((name) -> CodeBlock.of("$L.setImportMetadata(metadata)", name)).build()))
108-
.lines().containsExactly("(instanceContext) -> {",
109-
" ImportAwareConfiguration bean = new ImportAwareConfiguration();",
110-
" bean.setImportMetadata(metadata);",
111-
" return bean;",
112-
"}");
113-
}
114-
115-
@Test
116-
void writeConstructorWithInstanceCallbacks() {
117-
BeanDefinition beanDefinition = BeanDefinitionBuilder.rootBeanDefinition(ImportAwareConfiguration.class).getBeanDefinition();
118-
assertThat(generateCode(beanDefinition, (type) -> BeanInstanceDescriptor.of(type)
119-
.withInstanceCreator(ImportAwareConfiguration.class.getDeclaredConstructors()[0])
120-
.withInstanceCallback((name) -> CodeBlock.of("$L.setImportMetadata(metadata)", name))
121-
.withInstanceCallback((name) -> CodeBlock.of("$L.setImportMetadata(anotherMetadata)", name)).build()))
122-
.lines().containsExactly("(instanceContext) -> {",
123-
" ImportAwareConfiguration bean = new ImportAwareConfiguration();",
124-
" bean.setImportMetadata(metadata);",
125-
" bean.setImportMetadata(anotherMetadata);",
126-
" return bean;",
127-
"}");
128-
}
129-
130100
@Test
131101
void writeConstructorWithInjectionPoints() {
132102
BeanDefinition beanDefinition = BeanDefinitionBuilder.rootBeanDefinition(InjectionConfiguration.class).getBeanDefinition();
@@ -146,22 +116,6 @@ void writeConstructorWithInjectionPoints() {
146116

147117
}
148118

149-
@Test
150-
void writeConstructorWithInstanceCallbackAndInjectionPoint() {
151-
BeanDefinition beanDefinition = BeanDefinitionBuilder.rootBeanDefinition(ImportAwareConfiguration.class).getBeanDefinition();
152-
assertThat(generateCode(beanDefinition, (type) -> BeanInstanceDescriptor.of(type)
153-
.withInstanceCreator(ImportAwareConfiguration.class.getDeclaredConstructors()[0])
154-
.withInjectionPoint(ReflectionUtils.findMethod(ImportAwareConfiguration.class, "setEnvironment", Environment.class), true)
155-
.withInstanceCallback((name) -> CodeBlock.of("$L.setImportMetadata(metadata)", name)).build())).lines().containsOnly(
156-
"(instanceContext) -> {",
157-
" ImportAwareConfiguration bean = new ImportAwareConfiguration();",
158-
" bean.setImportMetadata(metadata);",
159-
" instanceContext.method(\"setEnvironment\", Environment.class)",
160-
" .invoke(context, (attributes) -> bean.setEnvironment(attributes.get(0)));",
161-
" return bean;",
162-
"}");
163-
}
164-
165119
@Test
166120
void writeMethodWithNoArgUseShortcut() {
167121
BeanDefinition beanDefinition = BeanDefinitionBuilder.rootBeanDefinition(String.class).getBeanDefinition();

spring-aot/src/test/java/org/springframework/context/bootstrap/generator/bean/descriptor/DefaultBeanInstanceDescriptorFactoryTests.java

-13
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,7 @@
2424
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
2525
import org.springframework.beans.factory.support.GenericBeanDefinition;
2626
import org.springframework.context.bootstrap.generator.sample.SimpleConfiguration;
27-
import org.springframework.context.bootstrap.generator.sample.callback.ImportAwareConfiguration;
2827
import org.springframework.context.bootstrap.generator.sample.injection.InjectionConfiguration;
29-
import org.springframework.context.bootstrap.generator.test.CodeSnippet;
3028
import org.springframework.core.env.Environment;
3129
import org.springframework.util.ReflectionUtils;
3230

@@ -62,20 +60,10 @@ void createWithConstructor() {
6260
assertThat(descriptor.getUserBeanClass()).isEqualTo(SimpleConfiguration.class);
6361
assertThat(descriptor.getInstanceCreator()).isNotNull();
6462
assertThat(descriptor.getInstanceCreator().getMember()).isEqualTo(SimpleConfiguration.class.getDeclaredConstructors()[0]);
65-
assertThat(descriptor.getInstanceCallbacks()).isEmpty();
6663
assertThat(descriptor.getInjectionPoints()).isEmpty();
6764
assertThat(descriptor.getProperties()).isEmpty();
6865
}
6966

70-
@Test
71-
void createWithInstanceCallback() {
72-
DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
73-
beanFactory.registerBeanDefinition("test", BeanDefinitionBuilder.rootBeanDefinition(ImportAwareConfiguration.class).getBeanDefinition());
74-
BeanInstanceDescriptor descriptor = createDescriptor(beanFactory, "test");
75-
assertThat(descriptor.getInstanceCallbacks()).singleElement().satisfies((callback) -> assertThat(CodeSnippet.of(callback.write("b")))
76-
.isEqualTo("ImportAwareInvoker.get(context).setAnnotationMetadata(b)"));
77-
}
78-
7967
@Test
8068
void createWithInjectionPoints() {
8169
DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
@@ -84,7 +72,6 @@ void createWithInjectionPoints() {
8472
assertThat(descriptor.getUserBeanClass()).isEqualTo(InjectionConfiguration.class);
8573
assertThat(descriptor.getInstanceCreator()).isNotNull();
8674
assertThat(descriptor.getInstanceCreator().getMember()).isEqualTo(InjectionConfiguration.class.getDeclaredConstructors()[0]);
87-
assertThat(descriptor.getInstanceCallbacks()).isEmpty();
8875
assertThat(descriptor.getInjectionPoints()).hasSize(2);
8976
assertThat(descriptor.getInjectionPoints()).anySatisfy((injectionPoint) -> {
9077
assertThat(injectionPoint.getMember()).isEqualTo(ReflectionUtils.findMethod(InjectionConfiguration.class, "setEnvironment", Environment.class));

0 commit comments

Comments
 (0)