Skip to content

Commit 6199835

Browse files
committed
Harmonize generated class name conventions
This commit moves the responsibility of naming classes to the GenerationContext. This was already largely the case before, except that the concept of a "mainTarget" and "featureNamePrefix" was specific to bean factory initialization contributors. ClassNameGenerator should now be instantiated with a default target and an optional feature name prefix. As a result, it does no longer generate class names in the "__" package. GeneratedClasses can now provide a new, unique, GeneratedClass or offer a container for retrieving the same GeneratedClass based on an identifier. This lets all contributors use this facility rather than creating JavaFile manually. This also means that ClassNameGenerator is no longer exposed. Because the naming conventions are now part of the GenerationContext, it is required to be able to retrieve a specialized version of it if a code generation round needs to use different naming conventions. A new withName method has been added to that effect. Closes gh-28585
1 parent b121eed commit 6199835

File tree

31 files changed

+645
-558
lines changed

31 files changed

+645
-558
lines changed

spring-aop/src/test/java/org/springframework/aop/scope/ScopedProxyBeanRegistrationAotProcessorTests.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@
4242
import org.springframework.beans.testfixture.beans.factory.aot.MockBeanFactoryInitializationCode;
4343
import org.springframework.beans.testfixture.beans.factory.generator.factory.NumberHolder;
4444
import org.springframework.core.ResolvableType;
45+
import org.springframework.core.testfixture.aot.generate.TestGenerationContext;
4546
import org.springframework.util.ReflectionUtils;
4647

4748
import static org.assertj.core.api.Assertions.assertThat;
@@ -71,7 +72,7 @@ void setup() {
7172
this.beanFactory = new DefaultListableBeanFactory();
7273
this.processor = new TestBeanRegistrationsAotProcessor();
7374
this.generatedFiles = new InMemoryGeneratedFiles();
74-
this.generationContext = new DefaultGenerationContext(this.generatedFiles);
75+
this.generationContext = new TestGenerationContext(this.generatedFiles);
7576
this.beanFactoryInitializationCode = new MockBeanFactoryInitializationCode();
7677
}
7778

spring-beans/src/main/java/org/springframework/beans/factory/annotation/AutowiredAnnotationBeanPostProcessor.java

Lines changed: 22 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@
4141
import org.apache.commons.logging.LogFactory;
4242

4343
import org.springframework.aot.generate.AccessVisibility;
44+
import org.springframework.aot.generate.GeneratedClass;
4445
import org.springframework.aot.generate.GenerationContext;
4546
import org.springframework.aot.generate.MethodReference;
4647
import org.springframework.aot.hint.ExecutableHint;
@@ -79,11 +80,8 @@
7980
import org.springframework.core.annotation.AnnotationUtils;
8081
import org.springframework.core.annotation.MergedAnnotation;
8182
import org.springframework.core.annotation.MergedAnnotations;
82-
import org.springframework.javapoet.ClassName;
8383
import org.springframework.javapoet.CodeBlock;
84-
import org.springframework.javapoet.JavaFile;
8584
import org.springframework.javapoet.MethodSpec;
86-
import org.springframework.javapoet.TypeSpec;
8785
import org.springframework.lang.Nullable;
8886
import org.springframework.util.Assert;
8987
import org.springframework.util.ClassUtils;
@@ -910,30 +908,28 @@ private static class AotContribution implements BeanRegistrationAotContribution
910908
@Override
911909
public void applyTo(GenerationContext generationContext,
912910
BeanRegistrationCode beanRegistrationCode) {
913-
914-
ClassName className = generationContext.getClassNameGenerator()
915-
.generateClassName(this.target, "Autowiring");
916-
TypeSpec.Builder classBuilder = TypeSpec.classBuilder(className);
917-
classBuilder.addJavadoc("Autowiring for {@link $T}.", this.target);
918-
classBuilder.addModifiers(javax.lang.model.element.Modifier.PUBLIC);
919-
classBuilder.addMethod(generateMethod(generationContext.getRuntimeHints()));
920-
JavaFile javaFile = JavaFile
921-
.builder(className.packageName(), classBuilder.build()).build();
922-
generationContext.getGeneratedFiles().addSourceFile(javaFile);
911+
GeneratedClass generatedClass = generationContext.getGeneratedClasses()
912+
.forFeatureComponent("Autowiring", this.target)
913+
.generate(type -> {
914+
type.addJavadoc("Autowiring for {@link $T}.", this.target);
915+
type.addModifiers(javax.lang.model.element.Modifier.PUBLIC);
916+
});
917+
generatedClass.getMethodGenerator().generateMethod(APPLY_METHOD)
918+
.using(generateMethod(generationContext.getRuntimeHints()));
923919
beanRegistrationCode.addInstancePostProcessor(
924-
MethodReference.ofStatic(className, APPLY_METHOD));
925-
}
926-
927-
private MethodSpec generateMethod(RuntimeHints hints) {
928-
MethodSpec.Builder builder = MethodSpec.methodBuilder(APPLY_METHOD);
929-
builder.addJavadoc("Apply the autowiring.");
930-
builder.addModifiers(javax.lang.model.element.Modifier.PUBLIC,
931-
javax.lang.model.element.Modifier.STATIC);
932-
builder.addParameter(RegisteredBean.class, REGISTERED_BEAN_PARAMETER);
933-
builder.addParameter(this.target, INSTANCE_PARAMETER);
934-
builder.returns(this.target);
935-
builder.addCode(generateMethodCode(hints));
936-
return builder.build();
920+
MethodReference.ofStatic(generatedClass.getName(), APPLY_METHOD));
921+
}
922+
923+
private Consumer<MethodSpec.Builder> generateMethod(RuntimeHints hints) {
924+
return method -> {
925+
method.addJavadoc("Apply the autowiring.");
926+
method.addModifiers(javax.lang.model.element.Modifier.PUBLIC,
927+
javax.lang.model.element.Modifier.STATIC);
928+
method.addParameter(RegisteredBean.class, REGISTERED_BEAN_PARAMETER);
929+
method.addParameter(this.target, INSTANCE_PARAMETER);
930+
method.returns(this.target);
931+
method.addCode(generateMethodCode(hints));
932+
};
937933
}
938934

939935
private CodeBlock generateMethodCode(RuntimeHints hints) {

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

Lines changed: 12 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -21,19 +21,15 @@
2121

2222
import javax.lang.model.element.Modifier;
2323

24-
import org.springframework.aot.generate.ClassGenerator.JavaFileGenerator;
2524
import org.springframework.aot.generate.GeneratedClass;
2625
import org.springframework.aot.generate.GeneratedMethod;
27-
import org.springframework.aot.generate.GeneratedMethods;
2826
import org.springframework.aot.generate.GenerationContext;
2927
import org.springframework.aot.generate.MethodGenerator;
3028
import org.springframework.aot.generate.MethodNameGenerator;
3129
import org.springframework.aot.generate.MethodReference;
3230
import org.springframework.beans.factory.config.BeanDefinition;
3331
import org.springframework.beans.factory.support.RegisteredBean;
3432
import org.springframework.javapoet.ClassName;
35-
import org.springframework.javapoet.JavaFile;
36-
import org.springframework.javapoet.TypeSpec;
3733
import org.springframework.lang.Nullable;
3834

3935
/**
@@ -45,6 +41,8 @@
4541
*/
4642
class BeanDefinitionMethodGenerator {
4743

44+
private static final String FEATURE_NAME = "BeanDefinitions";
45+
4846
private final BeanDefinitionMethodGeneratorFactory methodGeneratorFactory;
4947

5048
private final RegisteredBean registeredBean;
@@ -81,22 +79,23 @@ class BeanDefinitionMethodGenerator {
8179
* Generate the method that returns the {@link BeanDefinition} to be
8280
* registered.
8381
* @param generationContext the generation context
84-
* @param featureNamePrefix the prefix to use for the feature name
8582
* @param beanRegistrationsCode the bean registrations code
8683
* @return a reference to the generated method.
8784
*/
8885
MethodReference generateBeanDefinitionMethod(GenerationContext generationContext,
89-
String featureNamePrefix, BeanRegistrationsCode beanRegistrationsCode) {
86+
BeanRegistrationsCode beanRegistrationsCode) {
9087

9188
BeanRegistrationCodeFragments codeFragments = getCodeFragments(generationContext,
92-
beanRegistrationsCode, featureNamePrefix);
89+
beanRegistrationsCode);
9390
Class<?> target = codeFragments.getTarget(this.registeredBean,
9491
this.constructorOrFactoryMethod);
9592
if (!target.getName().startsWith("java.")) {
96-
String featureName = featureNamePrefix + "BeanDefinitions";
97-
GeneratedClass generatedClass = generationContext.getClassGenerator()
98-
.getOrGenerateClass(new BeanDefinitionsJavaFileGenerator(target),
99-
target, featureName);
93+
GeneratedClass generatedClass = generationContext.getGeneratedClasses()
94+
.forFeatureComponent(FEATURE_NAME, target)
95+
.getOrGenerate(FEATURE_NAME, type -> {
96+
type.addJavadoc("Bean definitions for {@link $T}", target);
97+
type.addModifiers(Modifier.PUBLIC);
98+
});
10099
MethodGenerator methodGenerator = generatedClass.getMethodGenerator()
101100
.withName(getName());
102101
GeneratedMethod generatedMethod = generateBeanDefinitionMethod(
@@ -115,11 +114,10 @@ MethodReference generateBeanDefinitionMethod(GenerationContext generationContext
115114
}
116115

117116
private BeanRegistrationCodeFragments getCodeFragments(GenerationContext generationContext,
118-
BeanRegistrationsCode beanRegistrationsCode, String featureNamePrefix) {
117+
BeanRegistrationsCode beanRegistrationsCode) {
119118

120119
BeanRegistrationCodeFragments codeFragments = new DefaultBeanRegistrationCodeFragments(
121-
beanRegistrationsCode, this.registeredBean, this.methodGeneratorFactory,
122-
featureNamePrefix);
120+
beanRegistrationsCode, this.registeredBean, this.methodGeneratorFactory);
123121
for (BeanRegistrationAotContribution aotContribution : this.aotContributions) {
124122
codeFragments = aotContribution.customizeBeanRegistrationCodeFragments(generationContext, codeFragments);
125123
}
@@ -172,41 +170,4 @@ private String getSimpleBeanName(String beanName) {
172170
return beanName;
173171
}
174172

175-
176-
/**
177-
* {@link BeanDefinitionsJavaFileGenerator} to create the
178-
* {@code BeanDefinitions} file.
179-
*/
180-
private static class BeanDefinitionsJavaFileGenerator implements JavaFileGenerator {
181-
182-
private final Class<?> target;
183-
184-
185-
BeanDefinitionsJavaFileGenerator(Class<?> target) {
186-
this.target = target;
187-
}
188-
189-
190-
@Override
191-
public JavaFile generateJavaFile(ClassName className, GeneratedMethods methods) {
192-
TypeSpec.Builder classBuilder = TypeSpec.classBuilder(className);
193-
classBuilder.addJavadoc("Bean definitions for {@link $T}", this.target);
194-
classBuilder.addModifiers(Modifier.PUBLIC);
195-
methods.doWithMethodSpecs(classBuilder::addMethod);
196-
return JavaFile.builder(className.packageName(), classBuilder.build())
197-
.build();
198-
}
199-
200-
@Override
201-
public int hashCode() {
202-
return getClass().hashCode();
203-
}
204-
205-
@Override
206-
public boolean equals(Object obj) {
207-
return getClass() == obj.getClass();
208-
}
209-
210-
}
211-
212173
}

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

Lines changed: 0 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@
1818

1919
import org.springframework.aot.generate.MethodGenerator;
2020
import org.springframework.aot.generate.MethodReference;
21-
import org.springframework.lang.Nullable;
2221

2322
/**
2423
* Interface that can be used to configure the code that will be generated to
@@ -35,24 +34,6 @@ public interface BeanFactoryInitializationCode {
3534
*/
3635
String BEAN_FACTORY_VARIABLE = "beanFactory";
3736

38-
/**
39-
* Return the target class for this bean factory or {@code null} if there is
40-
* no target.
41-
* @return the target
42-
*/
43-
@Nullable
44-
default Class<?> getTarget() {
45-
return null;
46-
}
47-
48-
/**
49-
* Return the name of the bean factory or and empty string if no ID is available.
50-
* @return the bean factory name
51-
*/
52-
default String getName() {
53-
return "";
54-
}
55-
5637
/**
5738
* Return a {@link MethodGenerator} that can be used to add more methods to
5839
* the Initializing code.

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

Lines changed: 15 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -20,17 +20,15 @@
2020

2121
import javax.lang.model.element.Modifier;
2222

23+
import org.springframework.aot.generate.GeneratedClass;
2324
import org.springframework.aot.generate.GeneratedMethod;
24-
import org.springframework.aot.generate.GeneratedMethods;
2525
import org.springframework.aot.generate.GenerationContext;
2626
import org.springframework.aot.generate.MethodGenerator;
2727
import org.springframework.aot.generate.MethodReference;
2828
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
2929
import org.springframework.javapoet.ClassName;
3030
import org.springframework.javapoet.CodeBlock;
31-
import org.springframework.javapoet.JavaFile;
3231
import org.springframework.javapoet.MethodSpec;
33-
import org.springframework.javapoet.TypeSpec;
3432

3533
/**
3634
* AOT contribution from a {@link BeanRegistrationsAotProcessor} used to
@@ -61,24 +59,23 @@ class BeanRegistrationsAotContribution
6159
public void applyTo(GenerationContext generationContext,
6260
BeanFactoryInitializationCode beanFactoryInitializationCode) {
6361

64-
ClassName className = generationContext.getClassNameGenerator().generateClassName(
65-
beanFactoryInitializationCode.getTarget(),
66-
beanFactoryInitializationCode.getName() + "BeanFactoryRegistrations");
62+
GeneratedClass generatedClass = generationContext.getGeneratedClasses()
63+
.forFeature("BeanFactoryRegistrations").generate(type -> {
64+
type.addJavadoc("Register bean definitions for the bean factory.");
65+
type.addModifiers(Modifier.PUBLIC);
66+
});
6767
BeanRegistrationsCodeGenerator codeGenerator = new BeanRegistrationsCodeGenerator(
68-
className);
68+
generatedClass);
6969
GeneratedMethod registerMethod = codeGenerator.getMethodGenerator()
7070
.generateMethod("registerBeanDefinitions")
7171
.using(builder -> generateRegisterMethod(builder, generationContext,
72-
beanFactoryInitializationCode.getName(),
7372
codeGenerator));
74-
JavaFile javaFile = codeGenerator.generatedJavaFile(className);
75-
generationContext.getGeneratedFiles().addSourceFile(javaFile);
7673
beanFactoryInitializationCode
77-
.addInitializer(MethodReference.of(className, registerMethod.getName()));
74+
.addInitializer(MethodReference.of(generatedClass.getName(), registerMethod.getName()));
7875
}
7976

8077
private void generateRegisterMethod(MethodSpec.Builder builder,
81-
GenerationContext generationContext, String featureNamePrefix,
78+
GenerationContext generationContext,
8279
BeanRegistrationsCode beanRegistrationsCode) {
8380

8481
builder.addJavadoc("Register the bean definitions.");
@@ -88,7 +85,7 @@ private void generateRegisterMethod(MethodSpec.Builder builder,
8885
CodeBlock.Builder code = CodeBlock.builder();
8986
this.registrations.forEach((beanName, beanDefinitionMethodGenerator) -> {
9087
MethodReference beanDefinitionMethod = beanDefinitionMethodGenerator
91-
.generateBeanDefinitionMethod(generationContext, featureNamePrefix,
88+
.generateBeanDefinitionMethod(generationContext,
9289
beanRegistrationsCode);
9390
code.addStatement("$L.registerBeanDefinition($S, $L)",
9491
BEAN_FACTORY_PARAMETER_NAME, beanName,
@@ -103,33 +100,21 @@ private void generateRegisterMethod(MethodSpec.Builder builder,
103100
*/
104101
static class BeanRegistrationsCodeGenerator implements BeanRegistrationsCode {
105102

106-
private final ClassName className;
103+
private final GeneratedClass generatedClass;
107104

108-
private final GeneratedMethods generatedMethods = new GeneratedMethods();
109-
110-
111-
public BeanRegistrationsCodeGenerator(ClassName className) {
112-
this.className = className;
105+
public BeanRegistrationsCodeGenerator(GeneratedClass generatedClass) {
106+
this.generatedClass = generatedClass;
113107
}
114108

115109

116110
@Override
117111
public ClassName getClassName() {
118-
return this.className;
112+
return this.generatedClass.getName();
119113
}
120114

121115
@Override
122116
public MethodGenerator getMethodGenerator() {
123-
return this.generatedMethods;
124-
}
125-
126-
JavaFile generatedJavaFile(ClassName className) {
127-
TypeSpec.Builder classBuilder = TypeSpec.classBuilder(className);
128-
classBuilder.addJavadoc("Register bean definitions for the bean factory.");
129-
classBuilder.addModifiers(Modifier.PUBLIC);
130-
this.generatedMethods.doWithMethodSpecs(classBuilder::addMethod);
131-
return JavaFile.builder(className.packageName(), classBuilder.build())
132-
.build();
117+
return this.generatedClass.getMethodGenerator();
133118
}
134119

135120
}

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

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -54,18 +54,14 @@ class DefaultBeanRegistrationCodeFragments extends BeanRegistrationCodeFragments
5454

5555
private final BeanDefinitionMethodGeneratorFactory beanDefinitionMethodGeneratorFactory;
5656

57-
private final String featureNamePrefix;
58-
5957

6058
DefaultBeanRegistrationCodeFragments(BeanRegistrationsCode beanRegistrationsCode,
6159
RegisteredBean registeredBean,
62-
BeanDefinitionMethodGeneratorFactory beanDefinitionMethodGeneratorFactory,
63-
String featureNamePrefix) {
60+
BeanDefinitionMethodGeneratorFactory beanDefinitionMethodGeneratorFactory) {
6461

6562
this.beanRegistrationsCode = beanRegistrationsCode;
6663
this.registeredBean = registeredBean;
6764
this.beanDefinitionMethodGeneratorFactory = beanDefinitionMethodGeneratorFactory;
68-
this.featureNamePrefix = featureNamePrefix;
6965
}
7066

7167

@@ -124,7 +120,7 @@ protected CodeBlock generateValueCode(GenerationContext generationContext,
124120
.getBeanDefinitionMethodGenerator(innerRegisteredBean, name);
125121
Assert.state(methodGenerator != null, "Unexpected filtering of inner-bean");
126122
MethodReference generatedMethod = methodGenerator
127-
.generateBeanDefinitionMethod(generationContext, this.featureNamePrefix,
123+
.generateBeanDefinitionMethod(generationContext,
128124
this.beanRegistrationsCode);
129125
return generatedMethod.toInvokeCodeBlock();
130126
}

0 commit comments

Comments
 (0)