Merge branch '6.0.x'
This commit is contained in:
commit
4d5e235166
|
|
@ -43,6 +43,7 @@ import org.springframework.aot.generate.GeneratedClass;
|
||||||
import org.springframework.aot.generate.GeneratedMethod;
|
import org.springframework.aot.generate.GeneratedMethod;
|
||||||
import org.springframework.aot.generate.GeneratedMethods;
|
import org.springframework.aot.generate.GeneratedMethods;
|
||||||
import org.springframework.aot.generate.GenerationContext;
|
import org.springframework.aot.generate.GenerationContext;
|
||||||
|
import org.springframework.aot.generate.MethodReference.ArgumentCodeGenerator;
|
||||||
import org.springframework.aot.hint.RuntimeHints;
|
import org.springframework.aot.hint.RuntimeHints;
|
||||||
import org.springframework.beans.BeanUtils;
|
import org.springframework.beans.BeanUtils;
|
||||||
import org.springframework.beans.PropertyValues;
|
import org.springframework.beans.PropertyValues;
|
||||||
|
|
@ -769,11 +770,11 @@ public class PersistenceAnnotationBeanPostProcessor implements InstantiationAwar
|
||||||
|
|
||||||
private final Class<?> target;
|
private final Class<?> target;
|
||||||
|
|
||||||
private final Collection<InjectedElement> injectedElements;
|
private final List<InjectedElement> injectedElements;
|
||||||
|
|
||||||
AotContribution(Class<?> target, Collection<InjectedElement> injectedElements) {
|
AotContribution(Class<?> target, Collection<InjectedElement> injectedElements) {
|
||||||
this.target = target;
|
this.target = target;
|
||||||
this.injectedElements = injectedElements;
|
this.injectedElements = List.copyOf(injectedElements);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
@ -797,19 +798,47 @@ public class PersistenceAnnotationBeanPostProcessor implements InstantiationAwar
|
||||||
|
|
||||||
private CodeBlock generateMethodCode(RuntimeHints hints, GeneratedClass generatedClass) {
|
private CodeBlock generateMethodCode(RuntimeHints hints, GeneratedClass generatedClass) {
|
||||||
CodeBlock.Builder code = CodeBlock.builder();
|
CodeBlock.Builder code = CodeBlock.builder();
|
||||||
InjectionCodeGenerator injectionCodeGenerator =
|
if (this.injectedElements.size() == 1) {
|
||||||
new InjectionCodeGenerator(generatedClass.getName(), hints);
|
code.add(generateInjectedElementMethodCode(hints, generatedClass, this.injectedElements.get(0)));
|
||||||
for (InjectedElement injectedElement : this.injectedElements) {
|
}
|
||||||
CodeBlock resourceToInject = generateResourceToInjectCode(generatedClass.getMethods(),
|
else {
|
||||||
(PersistenceElement) injectedElement);
|
for (InjectedElement injectedElement : this.injectedElements) {
|
||||||
code.add(injectionCodeGenerator.generateInjectionCode(
|
code.addStatement(applyInjectedElement(hints, generatedClass, injectedElement));
|
||||||
injectedElement.getMember(), INSTANCE_PARAMETER,
|
}
|
||||||
resourceToInject));
|
|
||||||
}
|
}
|
||||||
code.addStatement("return $L", INSTANCE_PARAMETER);
|
code.addStatement("return $L", INSTANCE_PARAMETER);
|
||||||
return code.build();
|
return code.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private CodeBlock applyInjectedElement(RuntimeHints hints, GeneratedClass generatedClass, InjectedElement injectedElement) {
|
||||||
|
String injectedElementName = injectedElement.getMember().getName();
|
||||||
|
GeneratedMethod generatedMethod = generatedClass.getMethods().add(new String[] { "apply", injectedElementName }, method -> {
|
||||||
|
method.addJavadoc("Apply the persistence injection for '$L'.", injectedElementName);
|
||||||
|
method.addModifiers(javax.lang.model.element.Modifier.PRIVATE,
|
||||||
|
javax.lang.model.element.Modifier.STATIC);
|
||||||
|
method.addParameter(RegisteredBean.class, REGISTERED_BEAN_PARAMETER);
|
||||||
|
method.addParameter(this.target, INSTANCE_PARAMETER);
|
||||||
|
method.addCode(generateInjectedElementMethodCode(hints, generatedClass, injectedElement));
|
||||||
|
});
|
||||||
|
ArgumentCodeGenerator argumentCodeGenerator = ArgumentCodeGenerator
|
||||||
|
.of(RegisteredBean.class, REGISTERED_BEAN_PARAMETER).and(this.target, INSTANCE_PARAMETER);
|
||||||
|
return generatedMethod.toMethodReference().toInvokeCodeBlock(argumentCodeGenerator, generatedClass.getName());
|
||||||
|
}
|
||||||
|
|
||||||
|
private CodeBlock generateInjectedElementMethodCode(RuntimeHints hints, GeneratedClass generatedClass,
|
||||||
|
InjectedElement injectedElement) {
|
||||||
|
|
||||||
|
CodeBlock.Builder code = CodeBlock.builder();
|
||||||
|
InjectionCodeGenerator injectionCodeGenerator =
|
||||||
|
new InjectionCodeGenerator(generatedClass.getName(), hints);
|
||||||
|
CodeBlock resourceToInject = generateResourceToInjectCode(generatedClass.getMethods(),
|
||||||
|
(PersistenceElement) injectedElement);
|
||||||
|
code.add(injectionCodeGenerator.generateInjectionCode(
|
||||||
|
injectedElement.getMember(), INSTANCE_PARAMETER,
|
||||||
|
resourceToInject));
|
||||||
|
return code.build();
|
||||||
|
}
|
||||||
|
|
||||||
private CodeBlock generateResourceToInjectCode(
|
private CodeBlock generateResourceToInjectCode(
|
||||||
GeneratedMethods generatedMethods, PersistenceElement injectedElement) {
|
GeneratedMethods generatedMethods, PersistenceElement injectedElement) {
|
||||||
|
|
||||||
|
|
@ -821,7 +850,7 @@ public class PersistenceAnnotationBeanPostProcessor implements InstantiationAwar
|
||||||
EntityManagerFactoryUtils.class, ListableBeanFactory.class,
|
EntityManagerFactoryUtils.class, ListableBeanFactory.class,
|
||||||
REGISTERED_BEAN_PARAMETER, unitName);
|
REGISTERED_BEAN_PARAMETER, unitName);
|
||||||
}
|
}
|
||||||
String[] methodNameParts = {"get", unitName, "EntityManager"};
|
String[] methodNameParts = { "get", unitName, "EntityManager" };
|
||||||
GeneratedMethod generatedMethod = generatedMethods.add(methodNameParts, method ->
|
GeneratedMethod generatedMethod = generatedMethods.add(methodNameParts, method ->
|
||||||
generateGetEntityManagerMethod(method, injectedElement));
|
generateGetEntityManagerMethod(method, injectedElement));
|
||||||
return CodeBlock.of("$L($L)", generatedMethod.getName(), REGISTERED_BEAN_PARAMETER);
|
return CodeBlock.of("$L($L)", generatedMethod.getName(), REGISTERED_BEAN_PARAMETER);
|
||||||
|
|
|
||||||
|
|
@ -32,6 +32,7 @@ import org.assertj.core.api.InstanceOfAssertFactories;
|
||||||
import org.junit.jupiter.api.BeforeEach;
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
import org.springframework.aot.hint.FieldHint;
|
||||||
import org.springframework.aot.hint.TypeReference;
|
import org.springframework.aot.hint.TypeReference;
|
||||||
import org.springframework.aot.test.generate.TestGenerationContext;
|
import org.springframework.aot.test.generate.TestGenerationContext;
|
||||||
import org.springframework.beans.factory.aot.BeanRegistrationAotContribution;
|
import org.springframework.beans.factory.aot.BeanRegistrationAotContribution;
|
||||||
|
|
@ -160,6 +161,28 @@ class PersistenceAnnotationBeanPostProcessorAotContributionTests {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void processAheadOfTimeWhenPersistenceContextOnPrivateFields() {
|
||||||
|
RegisteredBean registeredBean = registerBean(
|
||||||
|
SeveralPersistenceContextField.class);
|
||||||
|
testCompile(registeredBean, (actual, compiled) -> {
|
||||||
|
EntityManagerFactory entityManagerFactory = mock();
|
||||||
|
this.beanFactory.registerSingleton("custom", entityManagerFactory);
|
||||||
|
this.beanFactory.registerAlias("custom", "another");
|
||||||
|
SeveralPersistenceContextField instance = new SeveralPersistenceContextField();
|
||||||
|
actual.accept(registeredBean, instance);
|
||||||
|
assertThat(instance).extracting("customEntityManager").isNotNull();
|
||||||
|
assertThat(instance).extracting("anotherEntityManager").isNotNull();
|
||||||
|
assertThat(this.generationContext.getRuntimeHints().reflection().typeHints())
|
||||||
|
.singleElement().satisfies(typeHint -> {
|
||||||
|
assertThat(typeHint.getType()).isEqualTo(
|
||||||
|
TypeReference.of(SeveralPersistenceContextField.class));
|
||||||
|
assertThat(typeHint.fields().map(FieldHint::getName))
|
||||||
|
.containsOnly("customEntityManager", "anotherEntityManager");
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
private RegisteredBean registerBean(Class<?> beanClass) {
|
private RegisteredBean registerBean(Class<?> beanClass) {
|
||||||
String beanName = "testBean";
|
String beanName = "testBean";
|
||||||
this.beanFactory.registerBeanDefinition(beanName,
|
this.beanFactory.registerBeanDefinition(beanName,
|
||||||
|
|
@ -256,4 +279,16 @@ class PersistenceAnnotationBeanPostProcessorAotContributionTests {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static class SeveralPersistenceContextField {
|
||||||
|
|
||||||
|
@SuppressWarnings("unused")
|
||||||
|
@PersistenceContext(name = "custom")
|
||||||
|
private EntityManager customEntityManager;
|
||||||
|
|
||||||
|
@SuppressWarnings("unused")
|
||||||
|
@PersistenceContext(name = "another")
|
||||||
|
private EntityManager anotherEntityManager;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue