Fix hint generation for Autowired fields

Close gh-28655
This commit is contained in:
Stephane Nicoll 2022-06-19 11:18:54 +02:00
parent 36012ffea9
commit 365481379d
2 changed files with 20 additions and 2 deletions

View File

@ -964,13 +964,13 @@ public class AutowiredAnnotationBeanPostProcessor implements SmartInstantiationA
private CodeBlock generateMethodStatementForField(Field field, boolean required, private CodeBlock generateMethodStatementForField(Field field, boolean required,
RuntimeHints hints) { RuntimeHints hints) {
hints.reflection().registerField(field, ALLOW_WRITE);
CodeBlock resolver = CodeBlock.of("$T.$L($S)", CodeBlock resolver = CodeBlock.of("$T.$L($S)",
AutowiredFieldValueResolver.class, AutowiredFieldValueResolver.class,
(!required) ? "forField" : "forRequiredField", field.getName()); (!required) ? "forField" : "forRequiredField", field.getName());
AccessVisibility visibility = AccessVisibility.forMember(field); AccessVisibility visibility = AccessVisibility.forMember(field);
if (visibility == AccessVisibility.PRIVATE if (visibility == AccessVisibility.PRIVATE
|| visibility == AccessVisibility.PROTECTED) { || visibility == AccessVisibility.PROTECTED) {
hints.reflection().registerField(field, ALLOW_WRITE);
return CodeBlock.of("$L.resolveAndSet($L, $L)", resolver, return CodeBlock.of("$L.resolveAndSet($L, $L)", resolver,
REGISTERED_BEAN_PARAMETER, INSTANCE_PARAMETER); REGISTERED_BEAN_PARAMETER, INSTANCE_PARAMETER);
} }

View File

@ -31,6 +31,8 @@ import org.springframework.aot.generate.GenerationContext;
import org.springframework.aot.generate.InMemoryGeneratedFiles; import org.springframework.aot.generate.InMemoryGeneratedFiles;
import org.springframework.aot.generate.MethodGenerator; import org.springframework.aot.generate.MethodGenerator;
import org.springframework.aot.generate.MethodReference; import org.springframework.aot.generate.MethodReference;
import org.springframework.aot.hint.RuntimeHints;
import org.springframework.aot.hint.RuntimeHintsPredicates;
import org.springframework.aot.test.generator.compile.CompileWithTargetClassAccess; import org.springframework.aot.test.generator.compile.CompileWithTargetClassAccess;
import org.springframework.aot.test.generator.compile.Compiled; import org.springframework.aot.test.generator.compile.Compiled;
import org.springframework.aot.test.generator.compile.TestCompiler; import org.springframework.aot.test.generator.compile.TestCompiler;
@ -51,7 +53,7 @@ import org.springframework.javapoet.TypeSpec;
import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThat;
/** /**
* Tests for {@link AutowiredAnnotationBeanRegistrationAotContribution}. * Tests for {@link AutowiredAnnotationBeanPostProcessor} for AOT contributions.
* *
* @author Phillip Webb * @author Phillip Webb
* @author Stephane Nicoll * @author Stephane Nicoll
@ -63,6 +65,8 @@ class AutowiredAnnotationBeanRegistrationAotContributionTests {
private GenerationContext generationContext; private GenerationContext generationContext;
private RuntimeHints runtimeHints;
private MockBeanRegistrationCode beanRegistrationCode; private MockBeanRegistrationCode beanRegistrationCode;
private DefaultListableBeanFactory beanFactory; private DefaultListableBeanFactory beanFactory;
@ -71,6 +75,7 @@ class AutowiredAnnotationBeanRegistrationAotContributionTests {
void setup() { void setup() {
this.generatedFiles = new InMemoryGeneratedFiles(); this.generatedFiles = new InMemoryGeneratedFiles();
this.generationContext = new DefaultGenerationContext(this.generatedFiles); this.generationContext = new DefaultGenerationContext(this.generatedFiles);
this.runtimeHints = this.generationContext.getRuntimeHints();
this.beanRegistrationCode = new MockBeanRegistrationCode(); this.beanRegistrationCode = new MockBeanRegistrationCode();
this.beanFactory = new DefaultListableBeanFactory(); this.beanFactory = new DefaultListableBeanFactory();
} }
@ -81,6 +86,9 @@ class AutowiredAnnotationBeanRegistrationAotContributionTests {
this.beanFactory.registerSingleton("environment", environment); this.beanFactory.registerSingleton("environment", environment);
RegisteredBean registeredBean = getAndApplyContribution( RegisteredBean registeredBean = getAndApplyContribution(
PrivateFieldInjectionSample.class); PrivateFieldInjectionSample.class);
assertThat(RuntimeHintsPredicates.reflection()
.onField(PrivateFieldInjectionSample.class, "environment").allowWrite())
.accepts(this.runtimeHints);
testCompiledResult(registeredBean, (postProcessor, compiled) -> { testCompiledResult(registeredBean, (postProcessor, compiled) -> {
PrivateFieldInjectionSample instance = new PrivateFieldInjectionSample(); PrivateFieldInjectionSample instance = new PrivateFieldInjectionSample();
postProcessor.apply(registeredBean, instance); postProcessor.apply(registeredBean, instance);
@ -97,6 +105,9 @@ class AutowiredAnnotationBeanRegistrationAotContributionTests {
this.beanFactory.registerSingleton("environment", environment); this.beanFactory.registerSingleton("environment", environment);
RegisteredBean registeredBean = getAndApplyContribution( RegisteredBean registeredBean = getAndApplyContribution(
PackagePrivateFieldInjectionSample.class); PackagePrivateFieldInjectionSample.class);
assertThat(RuntimeHintsPredicates.reflection()
.onField(PackagePrivateFieldInjectionSample.class, "environment").allowWrite())
.accepts(this.runtimeHints);
testCompiledResult(registeredBean, (postProcessor, compiled) -> { testCompiledResult(registeredBean, (postProcessor, compiled) -> {
PackagePrivateFieldInjectionSample instance = new PackagePrivateFieldInjectionSample(); PackagePrivateFieldInjectionSample instance = new PackagePrivateFieldInjectionSample();
postProcessor.apply(registeredBean, instance); postProcessor.apply(registeredBean, instance);
@ -112,6 +123,9 @@ class AutowiredAnnotationBeanRegistrationAotContributionTests {
this.beanFactory.registerSingleton("environment", environment); this.beanFactory.registerSingleton("environment", environment);
RegisteredBean registeredBean = getAndApplyContribution( RegisteredBean registeredBean = getAndApplyContribution(
PrivateMethodInjectionSample.class); PrivateMethodInjectionSample.class);
assertThat(RuntimeHintsPredicates.reflection()
.onMethod(PrivateMethodInjectionSample.class, "setTestBean").invoke())
.accepts(this.runtimeHints);
testCompiledResult(registeredBean, (postProcessor, compiled) -> { testCompiledResult(registeredBean, (postProcessor, compiled) -> {
PrivateMethodInjectionSample instance = new PrivateMethodInjectionSample(); PrivateMethodInjectionSample instance = new PrivateMethodInjectionSample();
postProcessor.apply(registeredBean, instance); postProcessor.apply(registeredBean, instance);
@ -128,6 +142,9 @@ class AutowiredAnnotationBeanRegistrationAotContributionTests {
this.beanFactory.registerSingleton("environment", environment); this.beanFactory.registerSingleton("environment", environment);
RegisteredBean registeredBean = getAndApplyContribution( RegisteredBean registeredBean = getAndApplyContribution(
PackagePrivateMethodInjectionSample.class); PackagePrivateMethodInjectionSample.class);
assertThat(RuntimeHintsPredicates.reflection()
.onMethod(PackagePrivateMethodInjectionSample.class, "setTestBean").introspect())
.accepts(this.runtimeHints);
testCompiledResult(registeredBean, (postProcessor, compiled) -> { testCompiledResult(registeredBean, (postProcessor, compiled) -> {
PackagePrivateMethodInjectionSample instance = new PackagePrivateMethodInjectionSample(); PackagePrivateMethodInjectionSample instance = new PackagePrivateMethodInjectionSample();
postProcessor.apply(registeredBean, instance); postProcessor.apply(registeredBean, instance);
@ -141,6 +158,7 @@ class AutowiredAnnotationBeanRegistrationAotContributionTests {
RegisteredBean registeredBean = registerBean(beanClass); RegisteredBean registeredBean = registerBean(beanClass);
BeanRegistrationAotContribution contribution = new AutowiredAnnotationBeanPostProcessor() BeanRegistrationAotContribution contribution = new AutowiredAnnotationBeanPostProcessor()
.processAheadOfTime(registeredBean); .processAheadOfTime(registeredBean);
assertThat(contribution).isNotNull();
contribution.applyTo(this.generationContext, this.beanRegistrationCode); contribution.applyTo(this.generationContext, this.beanRegistrationCode);
return registeredBean; return registeredBean;
} }