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
This commit is contained in:
@@ -30,6 +30,7 @@ import java.util.Map;
|
||||
import java.util.Properties;
|
||||
import java.util.TreeSet;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import jakarta.persistence.EntityManager;
|
||||
import jakarta.persistence.EntityManagerFactory;
|
||||
@@ -39,11 +40,10 @@ import jakarta.persistence.PersistenceProperty;
|
||||
import jakarta.persistence.PersistenceUnit;
|
||||
import jakarta.persistence.SynchronizationType;
|
||||
|
||||
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.MethodReference;
|
||||
import org.springframework.aot.hint.RuntimeHints;
|
||||
import org.springframework.beans.BeanUtils;
|
||||
@@ -70,11 +70,9 @@ import org.springframework.core.BridgeMethodResolver;
|
||||
import org.springframework.core.Ordered;
|
||||
import org.springframework.core.PriorityOrdered;
|
||||
import org.springframework.core.annotation.AnnotationUtils;
|
||||
import org.springframework.javapoet.ClassName;
|
||||
import org.springframework.javapoet.CodeBlock;
|
||||
import org.springframework.javapoet.JavaFile;
|
||||
import org.springframework.javapoet.MethodSpec;
|
||||
import org.springframework.javapoet.TypeSpec;
|
||||
import org.springframework.javapoet.MethodSpec.Builder;
|
||||
import org.springframework.jndi.JndiLocatorDelegate;
|
||||
import org.springframework.jndi.JndiTemplate;
|
||||
import org.springframework.lang.Nullable;
|
||||
@@ -789,34 +787,27 @@ public class PersistenceAnnotationBeanPostProcessor implements InstantiationAwar
|
||||
@Override
|
||||
public void applyTo(GenerationContext generationContext,
|
||||
BeanRegistrationCode beanRegistrationCode) {
|
||||
ClassName className = generationContext.getClassNameGenerator()
|
||||
.generateClassName(this.target, "PersistenceInjection");
|
||||
TypeSpec.Builder classBuilder = TypeSpec.classBuilder(className);
|
||||
classBuilder.addJavadoc("Persistence injection for {@link $T}.", this.target);
|
||||
classBuilder.addModifiers(javax.lang.model.element.Modifier.PUBLIC);
|
||||
GeneratedMethods methods = new GeneratedMethods(
|
||||
new MethodNameGenerator(APPLY_METHOD));
|
||||
classBuilder.addMethod(generateMethod(generationContext.getRuntimeHints(),
|
||||
className, methods));
|
||||
methods.doWithMethodSpecs(classBuilder::addMethod);
|
||||
JavaFile javaFile = JavaFile
|
||||
.builder(className.packageName(), classBuilder.build()).build();
|
||||
generationContext.getGeneratedFiles().addSourceFile(javaFile);
|
||||
GeneratedClass generatedClass = generationContext.getGeneratedClasses()
|
||||
.forFeatureComponent("PersistenceInjection", this.target).generate(type -> {
|
||||
type.addJavadoc("Persistence injection for {@link $T}.", this.target);
|
||||
type.addModifiers(javax.lang.model.element.Modifier.PUBLIC);
|
||||
});
|
||||
generatedClass.getMethodGenerator().generateMethod(APPLY_METHOD)
|
||||
.using(generateMethod(generationContext.getRuntimeHints(), generatedClass.getMethodGenerator()));
|
||||
beanRegistrationCode.addInstancePostProcessor(
|
||||
MethodReference.ofStatic(className, APPLY_METHOD));
|
||||
MethodReference.ofStatic(generatedClass.getName(), APPLY_METHOD));
|
||||
}
|
||||
|
||||
private MethodSpec generateMethod(RuntimeHints hints, ClassName className,
|
||||
MethodGenerator methodGenerator) {
|
||||
MethodSpec.Builder builder = MethodSpec.methodBuilder(APPLY_METHOD);
|
||||
builder.addJavadoc("Apply the persistence injection.");
|
||||
builder.addModifiers(javax.lang.model.element.Modifier.PUBLIC,
|
||||
javax.lang.model.element.Modifier.STATIC);
|
||||
builder.addParameter(RegisteredBean.class, REGISTERED_BEAN_PARAMETER);
|
||||
builder.addParameter(this.target, INSTANCE_PARAMETER);
|
||||
builder.returns(this.target);
|
||||
builder.addCode(generateMethodCode(hints, methodGenerator));
|
||||
return builder.build();
|
||||
private Consumer<Builder> generateMethod(RuntimeHints hints, MethodGenerator methodGenerator) {
|
||||
return method -> {
|
||||
method.addJavadoc("Apply the persistence injection.");
|
||||
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, methodGenerator));
|
||||
};
|
||||
}
|
||||
|
||||
private CodeBlock generateMethodCode(RuntimeHints hints,
|
||||
|
||||
@@ -43,6 +43,7 @@ import org.springframework.beans.factory.aot.BeanRegistrationCode;
|
||||
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
|
||||
import org.springframework.beans.factory.support.RegisteredBean;
|
||||
import org.springframework.beans.factory.support.RootBeanDefinition;
|
||||
import org.springframework.core.testfixture.aot.generate.TestGenerationContext;
|
||||
import org.springframework.util.ReflectionUtils;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
@@ -67,7 +68,7 @@ class PersistenceAnnotationBeanPostProcessorAotContributionTests {
|
||||
void setup() {
|
||||
this.beanFactory = new DefaultListableBeanFactory();
|
||||
this.generatedFiles = new InMemoryGeneratedFiles();
|
||||
this.generationContext = new DefaultGenerationContext(generatedFiles);
|
||||
this.generationContext = new TestGenerationContext(generatedFiles);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -183,6 +184,7 @@ class PersistenceAnnotationBeanPostProcessorAotContributionTests {
|
||||
.processAheadOfTime(registeredBean);
|
||||
BeanRegistrationCode beanRegistrationCode = mock(BeanRegistrationCode.class);
|
||||
contribution.applyTo(generationContext, beanRegistrationCode);
|
||||
generationContext.writeGeneratedContent();
|
||||
TestCompiler.forSystem().withFiles(generatedFiles)
|
||||
.compile(compiled -> result.accept(new Invoker(compiled), compiled));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user