Stop generating unnecessary reference to field type
This commit updates the generator to stop specifying a field type when reflection is necessary, or when a reference to a field should be retrieved as its name alone suffices. This could trigger package protected issues if the field type is not public. See gh-28047
This commit is contained in:
parent
e873715737
commit
9809752c3c
|
|
@ -224,7 +224,7 @@ public class InjectionGenerator {
|
|||
|
||||
CodeBlock generateFieldInjection(Field injectionPoint, boolean required) {
|
||||
Builder code = CodeBlock.builder();
|
||||
code.add("instanceContext.field($S, $T.class", injectionPoint.getName(), injectionPoint.getType());
|
||||
code.add("instanceContext.field($S", injectionPoint.getName());
|
||||
code.add(")\n").indent().indent();
|
||||
if (required) {
|
||||
code.add(".invoke(beanFactory, (attributes) ->");
|
||||
|
|
@ -236,8 +236,8 @@ public class InjectionGenerator {
|
|||
if (hasAssignment) {
|
||||
code.beginControlFlow("");
|
||||
String fieldName = String.format("%sField", injectionPoint.getName());
|
||||
code.addStatement("$T $L = $T.findField($T.class, $S, $T.class)", Field.class, fieldName, ReflectionUtils.class,
|
||||
injectionPoint.getDeclaringClass(), injectionPoint.getName(), injectionPoint.getType());
|
||||
code.addStatement("$T $L = $T.findField($T.class, $S)", Field.class, fieldName, ReflectionUtils.class,
|
||||
injectionPoint.getDeclaringClass(), injectionPoint.getName());
|
||||
code.addStatement("$T.makeAccessible($L)", ReflectionUtils.class, fieldName);
|
||||
code.addStatement("$T.setField($L, bean, attributes.get(0))", ReflectionUtils.class, fieldName);
|
||||
code.unindent().add("}");
|
||||
|
|
|
|||
|
|
@ -298,11 +298,10 @@ public final class BeanDefinitionRegistrar {
|
|||
/**
|
||||
* Create an {@link InjectedElementResolver} for the specified field.
|
||||
* @param name the name of the field
|
||||
* @param type the type of the field
|
||||
* @return a resolved for the specified field
|
||||
*/
|
||||
public InjectedElementResolver field(String name, Class<?> type) {
|
||||
return new InjectedFieldResolver(getField(name, type), this.beanName);
|
||||
public InjectedElementResolver field(String name) {
|
||||
return new InjectedFieldResolver(getField(name), this.beanName);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -315,9 +314,9 @@ public final class BeanDefinitionRegistrar {
|
|||
return new InjectedMethodResolver(getMethod(this.beanType, name, parameterTypes), this.beanType, this.beanName);
|
||||
}
|
||||
|
||||
private Field getField(String fieldName, Class<?> fieldType) {
|
||||
Field field = ReflectionUtils.findField(this.beanType, fieldName, fieldType);
|
||||
Assert.notNull(field, () -> "No field '" + fieldName + "' with type " + fieldType.getName() + " found on " + this.beanType);
|
||||
private Field getField(String fieldName) {
|
||||
Field field = ReflectionUtils.findField(this.beanType, fieldName);
|
||||
Assert.notNull(field, () -> "No field '" + fieldName + "' found on " + this.beanType.getName());
|
||||
return field;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -44,7 +44,7 @@ class AutowiredAnnotationBeanInstantiationContributionTests {
|
|||
void contributeWithPackageProtectedFieldInjection() {
|
||||
CodeContribution contribution = contribute(PackageProtectedFieldInjectionSample.class);
|
||||
assertThat(CodeSnippet.process(contribution.statements().toCodeBlock())).isEqualTo("""
|
||||
instanceContext.field("environment", Environment.class)
|
||||
instanceContext.field("environment")
|
||||
.invoke(beanFactory, (attributes) -> bean.environment = attributes.get(0))""");
|
||||
assertThat(contribution.runtimeHints().reflection().typeHints()).singleElement().satisfies(typeHint -> {
|
||||
assertThat(typeHint.getType()).isEqualTo(TypeReference.of(PackageProtectedFieldInjectionSample.class));
|
||||
|
|
@ -62,9 +62,9 @@ class AutowiredAnnotationBeanInstantiationContributionTests {
|
|||
void contributeWithPrivateFieldInjection() {
|
||||
CodeContribution contribution = contribute(PrivateFieldInjectionSample.class);
|
||||
assertThat(CodeSnippet.process(contribution.statements().toCodeBlock())).isEqualTo("""
|
||||
instanceContext.field("environment", Environment.class)
|
||||
instanceContext.field("environment")
|
||||
.invoke(beanFactory, (attributes) -> {
|
||||
Field environmentField = ReflectionUtils.findField(AutowiredAnnotationBeanInstantiationContributionTests.PrivateFieldInjectionSample.class, "environment", Environment.class);
|
||||
Field environmentField = ReflectionUtils.findField(AutowiredAnnotationBeanInstantiationContributionTests.PrivateFieldInjectionSample.class, "environment");
|
||||
ReflectionUtils.makeAccessible(environmentField);
|
||||
ReflectionUtils.setField(environmentField, bean, attributes.get(0));
|
||||
})""");
|
||||
|
|
@ -99,9 +99,9 @@ class AutowiredAnnotationBeanInstantiationContributionTests {
|
|||
void contributeWithInjectionPoints() {
|
||||
CodeContribution contribution = contribute(ResourceInjectionBean.class);
|
||||
assertThat(CodeSnippet.process(contribution.statements().toCodeBlock())).isEqualTo("""
|
||||
instanceContext.field("testBean", TestBean.class)
|
||||
instanceContext.field("testBean")
|
||||
.resolve(beanFactory, false).ifResolved((attributes) -> {
|
||||
Field testBeanField = ReflectionUtils.findField(AutowiredAnnotationBeanPostProcessorTests.ResourceInjectionBean.class, "testBean", TestBean.class);
|
||||
Field testBeanField = ReflectionUtils.findField(AutowiredAnnotationBeanPostProcessorTests.ResourceInjectionBean.class, "testBean");
|
||||
ReflectionUtils.makeAccessible(testBeanField);
|
||||
ReflectionUtils.setField(testBeanField, bean, attributes.get(0));
|
||||
});
|
||||
|
|
|
|||
|
|
@ -142,7 +142,7 @@ class InjectionGeneratorTests {
|
|||
void generateInjectionForRequiredField() {
|
||||
Field field = field(SampleBean.class, "counter");
|
||||
assertThat(generateInjection(field, true)).isEqualTo("""
|
||||
instanceContext.field("counter", Integer.class)
|
||||
instanceContext.field("counter")
|
||||
.invoke(beanFactory, (attributes) -> bean.counter = attributes.get(0))""");
|
||||
}
|
||||
|
||||
|
|
@ -150,7 +150,7 @@ class InjectionGeneratorTests {
|
|||
void generateInjectionForNonRequiredField() {
|
||||
Field field = field(SampleBean.class, "counter");
|
||||
assertThat(generateInjection(field, false)).isEqualTo("""
|
||||
instanceContext.field("counter", Integer.class)
|
||||
instanceContext.field("counter")
|
||||
.resolve(beanFactory, false).ifResolved((attributes) -> bean.counter = attributes.get(0))""");
|
||||
}
|
||||
|
||||
|
|
@ -158,9 +158,9 @@ class InjectionGeneratorTests {
|
|||
void generateInjectionForRequiredPrivateField() {
|
||||
Field field = field(SampleBean.class, "source");
|
||||
assertThat(generateInjection(field, true)).isEqualTo("""
|
||||
instanceContext.field("source", String.class)
|
||||
instanceContext.field("source")
|
||||
.invoke(beanFactory, (attributes) -> {
|
||||
Field sourceField = ReflectionUtils.findField(InjectionGeneratorTests.SampleBean.class, "source", String.class);
|
||||
Field sourceField = ReflectionUtils.findField(InjectionGeneratorTests.SampleBean.class, "source");
|
||||
ReflectionUtils.makeAccessible(sourceField);
|
||||
ReflectionUtils.setField(sourceField, bean, attributes.get(0));
|
||||
})""");
|
||||
|
|
|
|||
|
|
@ -257,8 +257,8 @@ class BeanDefinitionRegistrarTests {
|
|||
beanFactory.registerSingleton("environment", environment);
|
||||
BeanDefinitionRegistrar.of("test", InjectionSample.class).instanceSupplier(instanceContext -> {
|
||||
InjectionSample bean = new InjectionSample();
|
||||
instanceContext.field("environment", Environment.class).invoke(beanFactory,
|
||||
attributes -> bean.environment = (attributes.get(0)));
|
||||
instanceContext.field("environment").invoke(beanFactory, attributes ->
|
||||
bean.environment = (attributes.get(0)));
|
||||
return bean;
|
||||
}).register(beanFactory);
|
||||
assertBeanFactory(beanFactory, () -> {
|
||||
|
|
@ -271,11 +271,10 @@ class BeanDefinitionRegistrarTests {
|
|||
void registerWithInvalidField() {
|
||||
DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
|
||||
BeanDefinitionRegistrar.of("test", InjectionSample.class).instanceSupplier(instanceContext ->
|
||||
instanceContext.field("doesNotExist", Object.class).resolve(beanFactory)).register(beanFactory);
|
||||
instanceContext.field("doesNotExist").resolve(beanFactory)).register(beanFactory);
|
||||
assertThatThrownBy(() -> beanFactory.getBean(InjectionSample.class)
|
||||
).isInstanceOf(BeanCreationException.class)
|
||||
.hasMessageContaining("No field '%s' with type %s found", "doesNotExist", Object.class.getName())
|
||||
.hasMessageContaining(InjectionSample.class.getName());
|
||||
).isInstanceOf(BeanCreationException.class).hasMessageContaining(
|
||||
"No field 'doesNotExist' found on " + InjectionSample.class.getName());
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
|
|||
Loading…
Reference in New Issue