Migrate AOT tests to use GeneratedClasses and refine/polish AOT APIs
Migrate all AOT tests to make use of `GeneratedClasses` rather than directly generating Java files. This commit also refines and polishes AOT APIs to being greater consistency. Specifically: - The `MethodGenerator` interface has been removed in favor of working directly with `GeneratedMethods`. - The visibility of several constructors and methods has been reduced to package-private. - The `using(...)` and `builder` methods have been removed in favor of setting the `Consumer` callbacks directly as constructor arguments. - Variable names for builders are now named `type` or `method` depending on what they're building. Closes gh-28831
This commit is contained in:
@@ -42,6 +42,7 @@ import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import org.springframework.aot.generate.AccessVisibility;
|
||||
import org.springframework.aot.generate.GeneratedClass;
|
||||
import org.springframework.aot.generate.GeneratedMethod;
|
||||
import org.springframework.aot.generate.GenerationContext;
|
||||
import org.springframework.aot.generate.MethodReference;
|
||||
import org.springframework.aot.hint.ExecutableHint;
|
||||
@@ -81,7 +82,6 @@ import org.springframework.core.annotation.AnnotationUtils;
|
||||
import org.springframework.core.annotation.MergedAnnotation;
|
||||
import org.springframework.core.annotation.MergedAnnotations;
|
||||
import org.springframework.javapoet.CodeBlock;
|
||||
import org.springframework.javapoet.MethodSpec;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ClassUtils;
|
||||
@@ -881,8 +881,6 @@ public class AutowiredAnnotationBeanPostProcessor implements SmartInstantiationA
|
||||
*/
|
||||
private static class AotContribution implements BeanRegistrationAotContribution {
|
||||
|
||||
private static final String APPLY_METHOD = "apply";
|
||||
|
||||
private static final String REGISTERED_BEAN_PARAMETER = "registeredBean";
|
||||
|
||||
private static final String INSTANCE_PARAMETER = "instance";
|
||||
@@ -909,27 +907,21 @@ public class AutowiredAnnotationBeanPostProcessor implements SmartInstantiationA
|
||||
public void applyTo(GenerationContext generationContext,
|
||||
BeanRegistrationCode beanRegistrationCode) {
|
||||
GeneratedClass generatedClass = generationContext.getGeneratedClasses()
|
||||
.forFeatureComponent("Autowiring", this.target)
|
||||
.generate(type -> {
|
||||
.addForFeatureComponent("Autowiring", this.target, type -> {
|
||||
type.addJavadoc("Autowiring for {@link $T}.", this.target);
|
||||
type.addModifiers(javax.lang.model.element.Modifier.PUBLIC);
|
||||
});
|
||||
generatedClass.getMethodGenerator().generateMethod(APPLY_METHOD)
|
||||
.using(generateMethod(generationContext.getRuntimeHints()));
|
||||
beanRegistrationCode.addInstancePostProcessor(
|
||||
MethodReference.ofStatic(generatedClass.getName(), APPLY_METHOD));
|
||||
}
|
||||
|
||||
private Consumer<MethodSpec.Builder> generateMethod(RuntimeHints hints) {
|
||||
return method -> {
|
||||
GeneratedMethod generateMethod = generatedClass.getMethods().add("apply", method -> {
|
||||
method.addJavadoc("Apply the autowiring.");
|
||||
method.addModifiers(javax.lang.model.element.Modifier.PUBLIC,
|
||||
javax.lang.model.element.Modifier.STATIC);
|
||||
method.addParameter(RegisteredBean.class, REGISTERED_BEAN_PARAMETER);
|
||||
method.addParameter(this.target, INSTANCE_PARAMETER);
|
||||
method.returns(this.target);
|
||||
method.addCode(generateMethodCode(hints));
|
||||
};
|
||||
method.addCode(generateMethodCode(generationContext.getRuntimeHints()));
|
||||
});
|
||||
beanRegistrationCode.addInstancePostProcessor(
|
||||
MethodReference.ofStatic(generatedClass.getName(), generateMethod.getName()));
|
||||
}
|
||||
|
||||
private CodeBlock generateMethodCode(RuntimeHints hints) {
|
||||
|
||||
@@ -23,9 +23,9 @@ import javax.lang.model.element.Modifier;
|
||||
|
||||
import org.springframework.aot.generate.GeneratedClass;
|
||||
import org.springframework.aot.generate.GeneratedMethod;
|
||||
import org.springframework.aot.generate.GeneratedMethods;
|
||||
import org.springframework.aot.generate.GenerationContext;
|
||||
import org.springframework.aot.generate.MethodGenerator;
|
||||
import org.springframework.aot.generate.MethodNameGenerator;
|
||||
import org.springframework.aot.generate.MethodName;
|
||||
import org.springframework.aot.generate.MethodReference;
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
import org.springframework.beans.factory.support.RegisteredBean;
|
||||
@@ -41,8 +41,6 @@ import org.springframework.lang.Nullable;
|
||||
*/
|
||||
class BeanDefinitionMethodGenerator {
|
||||
|
||||
private static final String FEATURE_NAME = "BeanDefinitions";
|
||||
|
||||
private final BeanDefinitionMethodGeneratorFactory methodGeneratorFactory;
|
||||
|
||||
private final RegisteredBean registeredBean;
|
||||
@@ -91,23 +89,22 @@ class BeanDefinitionMethodGenerator {
|
||||
this.constructorOrFactoryMethod);
|
||||
if (!target.getName().startsWith("java.")) {
|
||||
GeneratedClass generatedClass = generationContext.getGeneratedClasses()
|
||||
.forFeatureComponent(FEATURE_NAME, target)
|
||||
.getOrGenerate(FEATURE_NAME, type -> {
|
||||
.getOrAddForFeatureComponent("BeanDefinitions", target, type -> {
|
||||
type.addJavadoc("Bean definitions for {@link $T}", target);
|
||||
type.addModifiers(Modifier.PUBLIC);
|
||||
});
|
||||
MethodGenerator methodGenerator = generatedClass.getMethodGenerator()
|
||||
.withName(getName());
|
||||
GeneratedMethods generatedMethods = generatedClass.getMethods()
|
||||
.withPrefix(getName());
|
||||
GeneratedMethod generatedMethod = generateBeanDefinitionMethod(
|
||||
generationContext, generatedClass.getName(), methodGenerator,
|
||||
generationContext, generatedClass.getName(), generatedMethods,
|
||||
codeFragments, Modifier.PUBLIC);
|
||||
return MethodReference.ofStatic(generatedClass.getName(),
|
||||
generatedMethod.getName());
|
||||
}
|
||||
MethodGenerator methodGenerator = beanRegistrationsCode.getMethodGenerator()
|
||||
.withName(getName());
|
||||
GeneratedMethods generatedMethods = beanRegistrationsCode.getMethods()
|
||||
.withPrefix(getName());
|
||||
GeneratedMethod generatedMethod = generateBeanDefinitionMethod(generationContext,
|
||||
beanRegistrationsCode.getClassName(), methodGenerator, codeFragments,
|
||||
beanRegistrationsCode.getClassName(), generatedMethods, codeFragments,
|
||||
Modifier.PRIVATE);
|
||||
return MethodReference.ofStatic(beanRegistrationsCode.getClassName(),
|
||||
generatedMethod.getName());
|
||||
@@ -126,22 +123,21 @@ class BeanDefinitionMethodGenerator {
|
||||
|
||||
private GeneratedMethod generateBeanDefinitionMethod(
|
||||
GenerationContext generationContext, ClassName className,
|
||||
MethodGenerator methodGenerator, BeanRegistrationCodeFragments codeFragments,
|
||||
GeneratedMethods generatedMethods, BeanRegistrationCodeFragments codeFragments,
|
||||
Modifier modifier) {
|
||||
|
||||
BeanRegistrationCodeGenerator codeGenerator = new BeanRegistrationCodeGenerator(
|
||||
className, methodGenerator, this.registeredBean,
|
||||
className, generatedMethods, this.registeredBean,
|
||||
this.constructorOrFactoryMethod, codeFragments);
|
||||
GeneratedMethod method = methodGenerator.generateMethod("get", "bean", "definition");
|
||||
this.aotContributions.forEach(aotContribution -> aotContribution
|
||||
.applyTo(generationContext, codeGenerator));
|
||||
return method.using(builder -> {
|
||||
builder.addJavadoc("Get the $L definition for '$L'",
|
||||
return generatedMethods.add("getBeanDefinition", method -> {
|
||||
method.addJavadoc("Get the $L definition for '$L'",
|
||||
(!this.registeredBean.isInnerBean()) ? "bean" : "inner-bean",
|
||||
getName());
|
||||
builder.addModifiers(modifier, Modifier.STATIC);
|
||||
builder.returns(BeanDefinition.class);
|
||||
builder.addCode(codeGenerator.generateCode(generationContext));
|
||||
method.addModifiers(modifier, Modifier.STATIC);
|
||||
method.returns(BeanDefinition.class);
|
||||
method.addCode(codeGenerator.generateCode(generationContext));
|
||||
});
|
||||
}
|
||||
|
||||
@@ -156,10 +152,10 @@ class BeanDefinitionMethodGenerator {
|
||||
while (nonGeneratedParent != null && nonGeneratedParent.isGeneratedBeanName()) {
|
||||
nonGeneratedParent = nonGeneratedParent.getParent();
|
||||
}
|
||||
return (nonGeneratedParent != null)
|
||||
? MethodNameGenerator.join(
|
||||
getSimpleBeanName(nonGeneratedParent.getBeanName()), "innerBean")
|
||||
: "innerBean";
|
||||
if (nonGeneratedParent != null) {
|
||||
return MethodName.of(getSimpleBeanName(nonGeneratedParent.getBeanName()), "innerBean").toString();
|
||||
}
|
||||
return "innerBean";
|
||||
}
|
||||
|
||||
private String getSimpleBeanName(String beanName) {
|
||||
|
||||
@@ -31,7 +31,7 @@ import java.util.function.Consumer;
|
||||
import java.util.function.Function;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
import org.springframework.aot.generate.MethodGenerator;
|
||||
import org.springframework.aot.generate.GeneratedMethods;
|
||||
import org.springframework.aot.hint.ExecutableHint;
|
||||
import org.springframework.aot.hint.ExecutableMode;
|
||||
import org.springframework.aot.hint.RuntimeHints;
|
||||
@@ -81,7 +81,7 @@ class BeanDefinitionPropertiesCodeGenerator {
|
||||
|
||||
private static final String BEAN_DEFINITION_VARIABLE = BeanRegistrationCodeFragments.BEAN_DEFINITION_VARIABLE;
|
||||
|
||||
private static final Consumer<ExecutableHint.Builder> INVOKE_HINT = hint -> hint.withMode(ExecutableMode.INVOKE);
|
||||
private static final Consumer<ExecutableHint.Builder> INVOKE_HINT = hint -> hint.withMode(ExecutableMode.INVOKE);
|
||||
|
||||
private static final BeanInfoFactory beanInfoFactory = new ExtendedBeanInfoFactory();
|
||||
|
||||
@@ -95,14 +95,14 @@ class BeanDefinitionPropertiesCodeGenerator {
|
||||
|
||||
|
||||
BeanDefinitionPropertiesCodeGenerator(RuntimeHints hints,
|
||||
Predicate<String> attributeFilter, MethodGenerator methodGenerator,
|
||||
Predicate<String> attributeFilter, GeneratedMethods generatedMethods,
|
||||
BiFunction<String, Object, CodeBlock> customValueCodeGenerator) {
|
||||
|
||||
this.hints = hints;
|
||||
this.attributeFilter = attributeFilter;
|
||||
this.customValueCodeGenerator = customValueCodeGenerator;
|
||||
this.valueCodeGenerator = new BeanDefinitionPropertyValueCodeGenerator(
|
||||
methodGenerator);
|
||||
generatedMethods);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -30,8 +30,7 @@ import java.util.TreeMap;
|
||||
import java.util.TreeSet;
|
||||
|
||||
import org.springframework.aot.generate.GeneratedMethod;
|
||||
import org.springframework.aot.generate.MethodGenerator;
|
||||
import org.springframework.aot.generate.MethodNameGenerator;
|
||||
import org.springframework.aot.generate.GeneratedMethods;
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
import org.springframework.beans.factory.config.BeanReference;
|
||||
import org.springframework.beans.factory.config.RuntimeBeanReference;
|
||||
@@ -57,7 +56,7 @@ class BeanDefinitionPropertyValueCodeGenerator {
|
||||
|
||||
static final CodeBlock NULL_VALUE_CODE_BLOCK = CodeBlock.of("null");
|
||||
|
||||
private final MethodGenerator methodGenerator;
|
||||
private final GeneratedMethods generatedMethods;
|
||||
|
||||
private final List<Delegate> delegates = List.of(
|
||||
new PrimitiveDelegate(),
|
||||
@@ -76,8 +75,8 @@ class BeanDefinitionPropertyValueCodeGenerator {
|
||||
);
|
||||
|
||||
|
||||
BeanDefinitionPropertyValueCodeGenerator(MethodGenerator methodGenerator) {
|
||||
this.methodGenerator = methodGenerator;
|
||||
BeanDefinitionPropertyValueCodeGenerator(GeneratedMethods generatedMethods) {
|
||||
this.generatedMethods = generatedMethods;
|
||||
}
|
||||
|
||||
|
||||
@@ -485,24 +484,22 @@ class BeanDefinitionPropertyValueCodeGenerator {
|
||||
|
||||
private <K, V> CodeBlock generateLinkedHashMapCode(Map<K, V> map,
|
||||
ResolvableType keyType, ResolvableType valueType) {
|
||||
GeneratedMethod method = BeanDefinitionPropertyValueCodeGenerator.this.methodGenerator
|
||||
.generateMethod(MethodNameGenerator.join("get", "map"))
|
||||
.using(builder -> {
|
||||
builder.addAnnotation(AnnotationSpec
|
||||
GeneratedMethod generatedMethod = generatedMethods.add("getMap", method -> {
|
||||
method.addAnnotation(AnnotationSpec
|
||||
.builder(SuppressWarnings.class)
|
||||
.addMember("value", "{\"rawtypes\", \"unchecked\"}")
|
||||
.build());
|
||||
builder.returns(Map.class);
|
||||
builder.addStatement("$T map = new $T($L)", Map.class,
|
||||
method.returns(Map.class);
|
||||
method.addStatement("$T map = new $T($L)", Map.class,
|
||||
LinkedHashMap.class, map.size());
|
||||
map.forEach((key, value) -> builder.addStatement("map.put($L, $L)",
|
||||
map.forEach((key, value) -> method.addStatement("map.put($L, $L)",
|
||||
BeanDefinitionPropertyValueCodeGenerator.this
|
||||
.generateCode(key, keyType),
|
||||
BeanDefinitionPropertyValueCodeGenerator.this
|
||||
.generateCode(value, valueType)));
|
||||
builder.addStatement("return map");
|
||||
method.addStatement("return map");
|
||||
});
|
||||
return CodeBlock.of("$L()", method.getName());
|
||||
return CodeBlock.of("$L()", generatedMethod.getName());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
|
||||
package org.springframework.beans.factory.aot;
|
||||
|
||||
import org.springframework.aot.generate.MethodGenerator;
|
||||
import org.springframework.aot.generate.GeneratedMethods;
|
||||
import org.springframework.aot.generate.MethodReference;
|
||||
|
||||
/**
|
||||
@@ -35,11 +35,10 @@ public interface BeanFactoryInitializationCode {
|
||||
String BEAN_FACTORY_VARIABLE = "beanFactory";
|
||||
|
||||
/**
|
||||
* Return a {@link MethodGenerator} that can be used to add more methods to
|
||||
* the Initializing code.
|
||||
* Return the {@link GeneratedMethods} being used by the Initializing code.
|
||||
* @return the method generator
|
||||
*/
|
||||
MethodGenerator getMethodGenerator();
|
||||
GeneratedMethods getMethods();
|
||||
|
||||
/**
|
||||
* Add an initializer method call.
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
|
||||
package org.springframework.beans.factory.aot;
|
||||
|
||||
import org.springframework.aot.generate.MethodGenerator;
|
||||
import org.springframework.aot.generate.GeneratedMethods;
|
||||
import org.springframework.aot.generate.MethodReference;
|
||||
import org.springframework.beans.factory.support.InstanceSupplier;
|
||||
import org.springframework.javapoet.ClassName;
|
||||
@@ -39,11 +39,10 @@ public interface BeanRegistrationCode {
|
||||
ClassName getClassName();
|
||||
|
||||
/**
|
||||
* Return a {@link MethodGenerator} that can be used to add more methods to
|
||||
* the registrations code.
|
||||
* Return a {@link GeneratedMethods} being used by the registrations code.
|
||||
* @return the method generator
|
||||
*/
|
||||
MethodGenerator getMethodGenerator();
|
||||
GeneratedMethods getMethods();
|
||||
|
||||
/**
|
||||
* Add an instance post processor method call to the registration code.
|
||||
|
||||
@@ -21,8 +21,8 @@ import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
import org.springframework.aot.generate.GeneratedMethods;
|
||||
import org.springframework.aot.generate.GenerationContext;
|
||||
import org.springframework.aot.generate.MethodGenerator;
|
||||
import org.springframework.aot.generate.MethodReference;
|
||||
import org.springframework.beans.factory.support.RegisteredBean;
|
||||
import org.springframework.javapoet.ClassName;
|
||||
@@ -41,7 +41,7 @@ class BeanRegistrationCodeGenerator implements BeanRegistrationCode {
|
||||
|
||||
private final ClassName className;
|
||||
|
||||
private final MethodGenerator methodGenerator;
|
||||
private final GeneratedMethods generatedMethods;
|
||||
|
||||
private final List<MethodReference> instancePostProcessors = new ArrayList<>();
|
||||
|
||||
@@ -52,12 +52,12 @@ class BeanRegistrationCodeGenerator implements BeanRegistrationCode {
|
||||
private final BeanRegistrationCodeFragments codeFragments;
|
||||
|
||||
|
||||
BeanRegistrationCodeGenerator(ClassName className, MethodGenerator methodGenerator,
|
||||
BeanRegistrationCodeGenerator(ClassName className, GeneratedMethods methodGenerator,
|
||||
RegisteredBean registeredBean, Executable constructorOrFactoryMethod,
|
||||
BeanRegistrationCodeFragments codeFragments) {
|
||||
|
||||
this.className = className;
|
||||
this.methodGenerator = methodGenerator;
|
||||
this.generatedMethods = methodGenerator;
|
||||
this.registeredBean = registeredBean;
|
||||
this.constructorOrFactoryMethod = constructorOrFactoryMethod;
|
||||
this.codeFragments = codeFragments;
|
||||
@@ -69,8 +69,8 @@ class BeanRegistrationCodeGenerator implements BeanRegistrationCode {
|
||||
}
|
||||
|
||||
@Override
|
||||
public MethodGenerator getMethodGenerator() {
|
||||
return this.methodGenerator;
|
||||
public GeneratedMethods getMethods() {
|
||||
return this.generatedMethods;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -22,8 +22,8 @@ import javax.lang.model.element.Modifier;
|
||||
|
||||
import org.springframework.aot.generate.GeneratedClass;
|
||||
import org.springframework.aot.generate.GeneratedMethod;
|
||||
import org.springframework.aot.generate.GeneratedMethods;
|
||||
import org.springframework.aot.generate.GenerationContext;
|
||||
import org.springframework.aot.generate.MethodGenerator;
|
||||
import org.springframework.aot.generate.MethodReference;
|
||||
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
|
||||
import org.springframework.javapoet.ClassName;
|
||||
@@ -60,27 +60,24 @@ class BeanRegistrationsAotContribution
|
||||
BeanFactoryInitializationCode beanFactoryInitializationCode) {
|
||||
|
||||
GeneratedClass generatedClass = generationContext.getGeneratedClasses()
|
||||
.forFeature("BeanFactoryRegistrations").generate(type -> {
|
||||
.addForFeature("BeanFactoryRegistrations", type -> {
|
||||
type.addJavadoc("Register bean definitions for the bean factory.");
|
||||
type.addModifiers(Modifier.PUBLIC);
|
||||
});
|
||||
BeanRegistrationsCodeGenerator codeGenerator = new BeanRegistrationsCodeGenerator(
|
||||
generatedClass);
|
||||
GeneratedMethod registerMethod = codeGenerator.getMethodGenerator()
|
||||
.generateMethod("registerBeanDefinitions")
|
||||
.using(builder -> generateRegisterMethod(builder, generationContext,
|
||||
codeGenerator));
|
||||
beanFactoryInitializationCode
|
||||
.addInitializer(MethodReference.of(generatedClass.getName(), registerMethod.getName()));
|
||||
BeanRegistrationsCodeGenerator codeGenerator = new BeanRegistrationsCodeGenerator(generatedClass);
|
||||
GeneratedMethod generatedMethod = codeGenerator.getMethods().add("registerBeanDefinitions", method ->
|
||||
generateRegisterMethod(method, generationContext, codeGenerator));
|
||||
beanFactoryInitializationCode.addInitializer(
|
||||
MethodReference.of(generatedClass.getName(), generatedMethod.getName()));
|
||||
}
|
||||
|
||||
private void generateRegisterMethod(MethodSpec.Builder builder,
|
||||
private void generateRegisterMethod(MethodSpec.Builder method,
|
||||
GenerationContext generationContext,
|
||||
BeanRegistrationsCode beanRegistrationsCode) {
|
||||
|
||||
builder.addJavadoc("Register the bean definitions.");
|
||||
builder.addModifiers(Modifier.PUBLIC);
|
||||
builder.addParameter(DefaultListableBeanFactory.class,
|
||||
method.addJavadoc("Register the bean definitions.");
|
||||
method.addModifiers(Modifier.PUBLIC);
|
||||
method.addParameter(DefaultListableBeanFactory.class,
|
||||
BEAN_FACTORY_PARAMETER_NAME);
|
||||
CodeBlock.Builder code = CodeBlock.builder();
|
||||
this.registrations.forEach((beanName, beanDefinitionMethodGenerator) -> {
|
||||
@@ -91,7 +88,7 @@ class BeanRegistrationsAotContribution
|
||||
BEAN_FACTORY_PARAMETER_NAME, beanName,
|
||||
beanDefinitionMethod.toInvokeCodeBlock());
|
||||
});
|
||||
builder.addCode(code.build());
|
||||
method.addCode(code.build());
|
||||
}
|
||||
|
||||
|
||||
@@ -113,8 +110,8 @@ class BeanRegistrationsAotContribution
|
||||
}
|
||||
|
||||
@Override
|
||||
public MethodGenerator getMethodGenerator() {
|
||||
return this.generatedClass.getMethodGenerator();
|
||||
public GeneratedMethods getMethods() {
|
||||
return this.generatedClass.getMethods();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
|
||||
package org.springframework.beans.factory.aot;
|
||||
|
||||
import org.springframework.aot.generate.MethodGenerator;
|
||||
import org.springframework.aot.generate.GeneratedMethods;
|
||||
import org.springframework.javapoet.ClassName;
|
||||
|
||||
/**
|
||||
@@ -35,10 +35,9 @@ public interface BeanRegistrationsCode {
|
||||
ClassName getClassName();
|
||||
|
||||
/**
|
||||
* Return a {@link MethodGenerator} that can be used to add more methods to
|
||||
* the registrations code.
|
||||
* Return a {@link GeneratedMethods} being used by the registrations code.
|
||||
* @return the method generator
|
||||
*/
|
||||
MethodGenerator getMethodGenerator();
|
||||
GeneratedMethods getMethods();
|
||||
|
||||
}
|
||||
|
||||
@@ -105,7 +105,7 @@ class DefaultBeanRegistrationCodeFragments extends BeanRegistrationCodeFragments
|
||||
|
||||
return new BeanDefinitionPropertiesCodeGenerator(
|
||||
generationContext.getRuntimeHints(), attributeFilter,
|
||||
beanRegistrationCode.getMethodGenerator(),
|
||||
beanRegistrationCode.getMethods(),
|
||||
(name, value) -> generateValueCode(generationContext, name, value))
|
||||
.generateCode(beanDefinition);
|
||||
}
|
||||
@@ -170,7 +170,7 @@ class DefaultBeanRegistrationCodeFragments extends BeanRegistrationCodeFragments
|
||||
|
||||
return new InstanceSupplierCodeGenerator(generationContext,
|
||||
beanRegistrationCode.getClassName(),
|
||||
beanRegistrationCode.getMethodGenerator(), allowDirectSupplierShortcut)
|
||||
beanRegistrationCode.getMethods(), allowDirectSupplierShortcut)
|
||||
.generateCode(this.registeredBean, constructorOrFactoryMethod);
|
||||
}
|
||||
|
||||
|
||||
@@ -26,8 +26,8 @@ import java.util.function.Consumer;
|
||||
|
||||
import org.springframework.aot.generate.AccessVisibility;
|
||||
import org.springframework.aot.generate.GeneratedMethod;
|
||||
import org.springframework.aot.generate.GeneratedMethods;
|
||||
import org.springframework.aot.generate.GenerationContext;
|
||||
import org.springframework.aot.generate.MethodGenerator;
|
||||
import org.springframework.aot.hint.ExecutableHint;
|
||||
import org.springframework.aot.hint.ExecutableMode;
|
||||
import org.springframework.beans.factory.support.InstanceSupplier;
|
||||
@@ -36,6 +36,7 @@ import org.springframework.core.ResolvableType;
|
||||
import org.springframework.javapoet.ClassName;
|
||||
import org.springframework.javapoet.CodeBlock;
|
||||
import org.springframework.javapoet.MethodSpec;
|
||||
import org.springframework.javapoet.MethodSpec.Builder;
|
||||
import org.springframework.util.ClassUtils;
|
||||
import org.springframework.util.function.ThrowingSupplier;
|
||||
|
||||
@@ -60,7 +61,7 @@ class InstanceSupplierCodeGenerator {
|
||||
|
||||
private static final CodeBlock NO_ARGS = CodeBlock.of("");
|
||||
|
||||
private static final Consumer<ExecutableHint.Builder> INTROSPECT = builder -> builder
|
||||
private static final Consumer<ExecutableHint.Builder> INTROSPECT = hint -> hint
|
||||
.withMode(ExecutableMode.INTROSPECT);
|
||||
|
||||
|
||||
@@ -68,18 +69,18 @@ class InstanceSupplierCodeGenerator {
|
||||
|
||||
private final ClassName className;
|
||||
|
||||
private final MethodGenerator methodGenerator;
|
||||
private final GeneratedMethods generatedMethods;
|
||||
|
||||
private final boolean allowDirectSupplierShortcut;
|
||||
|
||||
|
||||
InstanceSupplierCodeGenerator(GenerationContext generationContext,
|
||||
ClassName className, MethodGenerator methodGenerator,
|
||||
ClassName className, GeneratedMethods generatedMethods,
|
||||
boolean allowDirectSupplierShortcut) {
|
||||
|
||||
this.generationContext = generationContext;
|
||||
this.className = className;
|
||||
this.methodGenerator = methodGenerator;
|
||||
this.generatedMethods = generatedMethods;
|
||||
this.allowDirectSupplierShortcut = allowDirectSupplierShortcut;
|
||||
}
|
||||
|
||||
@@ -131,11 +132,11 @@ class InstanceSupplierCodeGenerator {
|
||||
return CodeBlock.of("$T.of($T::new)", ThrowingSupplier.class,
|
||||
declaringClass);
|
||||
}
|
||||
GeneratedMethod getInstanceMethod = generateGetInstanceMethod()
|
||||
.using(builder -> buildGetInstanceMethodForConstructor(builder, name,
|
||||
constructor, declaringClass, dependsOnBean, PRIVATE_STATIC));
|
||||
GeneratedMethod generatedMethod = generateGetInstanceMethod(method ->
|
||||
buildGetInstanceMethodForConstructor(method, name, constructor, declaringClass,
|
||||
dependsOnBean, PRIVATE_STATIC));
|
||||
return CodeBlock.of("$T.of($T::$L)", InstanceSupplier.class, this.className,
|
||||
getInstanceMethod.getName());
|
||||
generatedMethod.getName());
|
||||
}
|
||||
|
||||
private CodeBlock generateCodeForInaccessibleConstructor(String name,
|
||||
@@ -143,33 +144,33 @@ class InstanceSupplierCodeGenerator {
|
||||
|
||||
this.generationContext.getRuntimeHints().reflection()
|
||||
.registerConstructor(constructor);
|
||||
GeneratedMethod getInstanceMethod = generateGetInstanceMethod().using(builder -> {
|
||||
builder.addJavadoc("Instantiate the bean instance for '$L'.", name);
|
||||
builder.addModifiers(PRIVATE_STATIC);
|
||||
builder.returns(declaringClass);
|
||||
builder.addParameter(RegisteredBean.class, REGISTERED_BEAN_PARAMETER_NAME);
|
||||
GeneratedMethod generatedMethod = generateGetInstanceMethod(method -> {
|
||||
method.addJavadoc("Instantiate the bean instance for '$L'.", name);
|
||||
method.addModifiers(PRIVATE_STATIC);
|
||||
method.returns(declaringClass);
|
||||
method.addParameter(RegisteredBean.class, REGISTERED_BEAN_PARAMETER_NAME);
|
||||
int parameterOffset = (!dependsOnBean) ? 0 : 1;
|
||||
builder.addStatement(
|
||||
method.addStatement(
|
||||
generateResolverForConstructor(constructor, parameterOffset));
|
||||
builder.addStatement("return resolver.resolveAndInstantiate($L)",
|
||||
method.addStatement("return resolver.resolveAndInstantiate($L)",
|
||||
REGISTERED_BEAN_PARAMETER_NAME);
|
||||
});
|
||||
return CodeBlock.of("$T.of($T::$L)", InstanceSupplier.class, this.className,
|
||||
getInstanceMethod.getName());
|
||||
generatedMethod.getName());
|
||||
}
|
||||
|
||||
private void buildGetInstanceMethodForConstructor(MethodSpec.Builder builder,
|
||||
private void buildGetInstanceMethodForConstructor(MethodSpec.Builder method,
|
||||
String name, Constructor<?> constructor, Class<?> declaringClass,
|
||||
boolean dependsOnBean, javax.lang.model.element.Modifier... modifiers) {
|
||||
|
||||
builder.addJavadoc("Create the bean instance for '$L'.", name);
|
||||
builder.addModifiers(modifiers);
|
||||
builder.returns(declaringClass);
|
||||
builder.addParameter(RegisteredBean.class, REGISTERED_BEAN_PARAMETER_NAME);
|
||||
method.addJavadoc("Create the bean instance for '$L'.", name);
|
||||
method.addModifiers(modifiers);
|
||||
method.returns(declaringClass);
|
||||
method.addParameter(RegisteredBean.class, REGISTERED_BEAN_PARAMETER_NAME);
|
||||
if (constructor.getParameterCount() == 0) {
|
||||
CodeBlock instantiationCode = generateNewInstanceCodeForConstructor(
|
||||
dependsOnBean, declaringClass, NO_ARGS);
|
||||
builder.addCode(generateReturnStatement(instantiationCode));
|
||||
method.addCode(generateReturnStatement(instantiationCode));
|
||||
}
|
||||
else {
|
||||
int parameterOffset = (!dependsOnBean) ? 0 : 1;
|
||||
@@ -183,7 +184,7 @@ class InstanceSupplierCodeGenerator {
|
||||
declaringClass, arguments);
|
||||
code.addStatement("return resolver.resolve($L, (args) -> $L)",
|
||||
REGISTERED_BEAN_PARAMETER_NAME, newInstance);
|
||||
builder.addCode(code.build());
|
||||
method.addCode(code.build());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -241,11 +242,11 @@ class InstanceSupplierCodeGenerator {
|
||||
return CodeBlock.of("$T.of($T::$L)", ThrowingSupplier.class, declaringClass,
|
||||
factoryMethod.getName());
|
||||
}
|
||||
GeneratedMethod getInstanceMethod = generateGetInstanceMethod()
|
||||
.using(builder -> buildGetInstanceMethodForFactoryMethod(builder, name,
|
||||
factoryMethod, declaringClass, dependsOnBean, PRIVATE_STATIC));
|
||||
GeneratedMethod generatedMethod = generateGetInstanceMethod(method ->
|
||||
buildGetInstanceMethodForFactoryMethod(method, name, factoryMethod, declaringClass,
|
||||
dependsOnBean, PRIVATE_STATIC));
|
||||
return CodeBlock.of("$T.of($T::$L)", InstanceSupplier.class, this.className,
|
||||
getInstanceMethod.getName());
|
||||
generatedMethod.getName());
|
||||
}
|
||||
|
||||
private CodeBlock generateCodeForInaccessibleFactoryMethod(String name,
|
||||
@@ -253,36 +254,36 @@ class InstanceSupplierCodeGenerator {
|
||||
|
||||
this.generationContext.getRuntimeHints().reflection()
|
||||
.registerMethod(factoryMethod);
|
||||
GeneratedMethod getInstanceMethod = generateGetInstanceMethod().using(builder -> {
|
||||
builder.addJavadoc("Instantiate the bean instance for '$L'.", name);
|
||||
builder.addModifiers(PRIVATE_STATIC);
|
||||
builder.returns(factoryMethod.getReturnType());
|
||||
builder.addParameter(RegisteredBean.class, REGISTERED_BEAN_PARAMETER_NAME);
|
||||
builder.addStatement(generateResolverForFactoryMethod(factoryMethod,
|
||||
GeneratedMethod generatedMethod = generateGetInstanceMethod(method -> {
|
||||
method.addJavadoc("Instantiate the bean instance for '$L'.", name);
|
||||
method.addModifiers(PRIVATE_STATIC);
|
||||
method.returns(factoryMethod.getReturnType());
|
||||
method.addParameter(RegisteredBean.class, REGISTERED_BEAN_PARAMETER_NAME);
|
||||
method.addStatement(generateResolverForFactoryMethod(factoryMethod,
|
||||
declaringClass, factoryMethod.getName()));
|
||||
builder.addStatement("return resolver.resolveAndInstantiate($L)",
|
||||
method.addStatement("return resolver.resolveAndInstantiate($L)",
|
||||
REGISTERED_BEAN_PARAMETER_NAME);
|
||||
});
|
||||
return CodeBlock.of("$T.of($T::$L)", InstanceSupplier.class, this.className,
|
||||
getInstanceMethod.getName());
|
||||
generatedMethod.getName());
|
||||
}
|
||||
|
||||
private void buildGetInstanceMethodForFactoryMethod(MethodSpec.Builder builder,
|
||||
private void buildGetInstanceMethodForFactoryMethod(MethodSpec.Builder method,
|
||||
String name, Method factoryMethod, Class<?> declaringClass,
|
||||
boolean dependsOnBean, javax.lang.model.element.Modifier... modifiers) {
|
||||
|
||||
String factoryMethodName = factoryMethod.getName();
|
||||
builder.addJavadoc("Get the bean instance for '$L'.", name);
|
||||
builder.addModifiers(modifiers);
|
||||
builder.returns(factoryMethod.getReturnType());
|
||||
method.addJavadoc("Get the bean instance for '$L'.", name);
|
||||
method.addModifiers(modifiers);
|
||||
method.returns(factoryMethod.getReturnType());
|
||||
if (isThrowingCheckedException(factoryMethod)) {
|
||||
builder.addException(Exception.class);
|
||||
method.addException(Exception.class);
|
||||
}
|
||||
builder.addParameter(RegisteredBean.class, REGISTERED_BEAN_PARAMETER_NAME);
|
||||
method.addParameter(RegisteredBean.class, REGISTERED_BEAN_PARAMETER_NAME);
|
||||
if (factoryMethod.getParameterCount() == 0) {
|
||||
CodeBlock instantiationCode = generateNewInstanceCodeForMethod(dependsOnBean,
|
||||
declaringClass, factoryMethodName, NO_ARGS);
|
||||
builder.addCode(generateReturnStatement(instantiationCode));
|
||||
method.addCode(generateReturnStatement(instantiationCode));
|
||||
}
|
||||
else {
|
||||
CodeBlock.Builder code = CodeBlock.builder();
|
||||
@@ -294,7 +295,7 @@ class InstanceSupplierCodeGenerator {
|
||||
declaringClass, factoryMethodName, arguments);
|
||||
code.addStatement("return resolver.resolve($L, (args) -> $L)",
|
||||
REGISTERED_BEAN_PARAMETER_NAME, newInstance);
|
||||
builder.addCode(code.build());
|
||||
method.addCode(code.build());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -349,8 +350,8 @@ class InstanceSupplierCodeGenerator {
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
private GeneratedMethod generateGetInstanceMethod() {
|
||||
return this.methodGenerator.generateMethod("get", "instance");
|
||||
private GeneratedMethod generateGetInstanceMethod(Consumer<Builder> method) {
|
||||
return this.generatedMethods.add("getInstance", method);
|
||||
}
|
||||
|
||||
private boolean isThrowingCheckedException(Executable executable) {
|
||||
|
||||
Reference in New Issue
Block a user