Skip to content

Commit 9809752

Browse files
committed
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
1 parent e873715 commit 9809752

File tree

5 files changed

+22
-24
lines changed

5 files changed

+22
-24
lines changed

spring-beans/src/main/java/org/springframework/beans/factory/generator/InjectionGenerator.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -224,7 +224,7 @@ private CodeBlock generateMethodInvocation(Method injectionPoint, Consumer<Build
224224

225225
CodeBlock generateFieldInjection(Field injectionPoint, boolean required) {
226226
Builder code = CodeBlock.builder();
227-
code.add("instanceContext.field($S, $T.class", injectionPoint.getName(), injectionPoint.getType());
227+
code.add("instanceContext.field($S", injectionPoint.getName());
228228
code.add(")\n").indent().indent();
229229
if (required) {
230230
code.add(".invoke(beanFactory, (attributes) ->");
@@ -236,8 +236,8 @@ CodeBlock generateFieldInjection(Field injectionPoint, boolean required) {
236236
if (hasAssignment) {
237237
code.beginControlFlow("");
238238
String fieldName = String.format("%sField", injectionPoint.getName());
239-
code.addStatement("$T $L = $T.findField($T.class, $S, $T.class)", Field.class, fieldName, ReflectionUtils.class,
240-
injectionPoint.getDeclaringClass(), injectionPoint.getName(), injectionPoint.getType());
239+
code.addStatement("$T $L = $T.findField($T.class, $S)", Field.class, fieldName, ReflectionUtils.class,
240+
injectionPoint.getDeclaringClass(), injectionPoint.getName());
241241
code.addStatement("$T.makeAccessible($L)", ReflectionUtils.class, fieldName);
242242
code.addStatement("$T.setField($L, bean, attributes.get(0))", ReflectionUtils.class, fieldName);
243243
code.unindent().add("}");

spring-beans/src/main/java/org/springframework/beans/factory/generator/config/BeanDefinitionRegistrar.java

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -298,11 +298,10 @@ private InjectedElementResolver resolveInstanceCreator(@Nullable Executable inst
298298
/**
299299
* Create an {@link InjectedElementResolver} for the specified field.
300300
* @param name the name of the field
301-
* @param type the type of the field
302301
* @return a resolved for the specified field
303302
*/
304-
public InjectedElementResolver field(String name, Class<?> type) {
305-
return new InjectedFieldResolver(getField(name, type), this.beanName);
303+
public InjectedElementResolver field(String name) {
304+
return new InjectedFieldResolver(getField(name), this.beanName);
306305
}
307306

308307
/**
@@ -315,9 +314,9 @@ public InjectedElementResolver method(String name, Class<?>... parameterTypes) {
315314
return new InjectedMethodResolver(getMethod(this.beanType, name, parameterTypes), this.beanType, this.beanName);
316315
}
317316

318-
private Field getField(String fieldName, Class<?> fieldType) {
319-
Field field = ReflectionUtils.findField(this.beanType, fieldName, fieldType);
320-
Assert.notNull(field, () -> "No field '" + fieldName + "' with type " + fieldType.getName() + " found on " + this.beanType);
317+
private Field getField(String fieldName) {
318+
Field field = ReflectionUtils.findField(this.beanType, fieldName);
319+
Assert.notNull(field, () -> "No field '" + fieldName + "' found on " + this.beanType.getName());
321320
return field;
322321
}
323322

spring-beans/src/test/java/org/springframework/beans/factory/annotation/AutowiredAnnotationBeanInstantiationContributorTests.java

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ class AutowiredAnnotationBeanInstantiationContributionTests {
4444
void contributeWithPackageProtectedFieldInjection() {
4545
CodeContribution contribution = contribute(PackageProtectedFieldInjectionSample.class);
4646
assertThat(CodeSnippet.process(contribution.statements().toCodeBlock())).isEqualTo("""
47-
instanceContext.field("environment", Environment.class)
47+
instanceContext.field("environment")
4848
.invoke(beanFactory, (attributes) -> bean.environment = attributes.get(0))""");
4949
assertThat(contribution.runtimeHints().reflection().typeHints()).singleElement().satisfies(typeHint -> {
5050
assertThat(typeHint.getType()).isEqualTo(TypeReference.of(PackageProtectedFieldInjectionSample.class));
@@ -62,9 +62,9 @@ void contributeWithPackageProtectedFieldInjection() {
6262
void contributeWithPrivateFieldInjection() {
6363
CodeContribution contribution = contribute(PrivateFieldInjectionSample.class);
6464
assertThat(CodeSnippet.process(contribution.statements().toCodeBlock())).isEqualTo("""
65-
instanceContext.field("environment", Environment.class)
65+
instanceContext.field("environment")
6666
.invoke(beanFactory, (attributes) -> {
67-
Field environmentField = ReflectionUtils.findField(AutowiredAnnotationBeanInstantiationContributionTests.PrivateFieldInjectionSample.class, "environment", Environment.class);
67+
Field environmentField = ReflectionUtils.findField(AutowiredAnnotationBeanInstantiationContributionTests.PrivateFieldInjectionSample.class, "environment");
6868
ReflectionUtils.makeAccessible(environmentField);
6969
ReflectionUtils.setField(environmentField, bean, attributes.get(0));
7070
})""");
@@ -99,9 +99,9 @@ void contributeWithPublicMethodInjection() {
9999
void contributeWithInjectionPoints() {
100100
CodeContribution contribution = contribute(ResourceInjectionBean.class);
101101
assertThat(CodeSnippet.process(contribution.statements().toCodeBlock())).isEqualTo("""
102-
instanceContext.field("testBean", TestBean.class)
102+
instanceContext.field("testBean")
103103
.resolve(beanFactory, false).ifResolved((attributes) -> {
104-
Field testBeanField = ReflectionUtils.findField(AutowiredAnnotationBeanPostProcessorTests.ResourceInjectionBean.class, "testBean", TestBean.class);
104+
Field testBeanField = ReflectionUtils.findField(AutowiredAnnotationBeanPostProcessorTests.ResourceInjectionBean.class, "testBean");
105105
ReflectionUtils.makeAccessible(testBeanField);
106106
ReflectionUtils.setField(testBeanField, bean, attributes.get(0));
107107
});

spring-beans/src/test/java/org/springframework/beans/factory/generator/InjectionGeneratorTests.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -142,25 +142,25 @@ void generateInjectionForNonRequiredMethodWithGenericParameter() {
142142
void generateInjectionForRequiredField() {
143143
Field field = field(SampleBean.class, "counter");
144144
assertThat(generateInjection(field, true)).isEqualTo("""
145-
instanceContext.field("counter", Integer.class)
145+
instanceContext.field("counter")
146146
.invoke(beanFactory, (attributes) -> bean.counter = attributes.get(0))""");
147147
}
148148

149149
@Test
150150
void generateInjectionForNonRequiredField() {
151151
Field field = field(SampleBean.class, "counter");
152152
assertThat(generateInjection(field, false)).isEqualTo("""
153-
instanceContext.field("counter", Integer.class)
153+
instanceContext.field("counter")
154154
.resolve(beanFactory, false).ifResolved((attributes) -> bean.counter = attributes.get(0))""");
155155
}
156156

157157
@Test
158158
void generateInjectionForRequiredPrivateField() {
159159
Field field = field(SampleBean.class, "source");
160160
assertThat(generateInjection(field, true)).isEqualTo("""
161-
instanceContext.field("source", String.class)
161+
instanceContext.field("source")
162162
.invoke(beanFactory, (attributes) -> {
163-
Field sourceField = ReflectionUtils.findField(InjectionGeneratorTests.SampleBean.class, "source", String.class);
163+
Field sourceField = ReflectionUtils.findField(InjectionGeneratorTests.SampleBean.class, "source");
164164
ReflectionUtils.makeAccessible(sourceField);
165165
ReflectionUtils.setField(sourceField, bean, attributes.get(0));
166166
})""");

spring-beans/src/test/java/org/springframework/beans/factory/generator/config/BeanDefinitionRegistrarTests.java

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -257,8 +257,8 @@ void registerWithInjectedField() {
257257
beanFactory.registerSingleton("environment", environment);
258258
BeanDefinitionRegistrar.of("test", InjectionSample.class).instanceSupplier(instanceContext -> {
259259
InjectionSample bean = new InjectionSample();
260-
instanceContext.field("environment", Environment.class).invoke(beanFactory,
261-
attributes -> bean.environment = (attributes.get(0)));
260+
instanceContext.field("environment").invoke(beanFactory, attributes ->
261+
bean.environment = (attributes.get(0)));
262262
return bean;
263263
}).register(beanFactory);
264264
assertBeanFactory(beanFactory, () -> {
@@ -271,11 +271,10 @@ void registerWithInjectedField() {
271271
void registerWithInvalidField() {
272272
DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
273273
BeanDefinitionRegistrar.of("test", InjectionSample.class).instanceSupplier(instanceContext ->
274-
instanceContext.field("doesNotExist", Object.class).resolve(beanFactory)).register(beanFactory);
274+
instanceContext.field("doesNotExist").resolve(beanFactory)).register(beanFactory);
275275
assertThatThrownBy(() -> beanFactory.getBean(InjectionSample.class)
276-
).isInstanceOf(BeanCreationException.class)
277-
.hasMessageContaining("No field '%s' with type %s found", "doesNotExist", Object.class.getName())
278-
.hasMessageContaining(InjectionSample.class.getName());
276+
).isInstanceOf(BeanCreationException.class).hasMessageContaining(
277+
"No field 'doesNotExist' found on " + InjectionSample.class.getName());
279278
}
280279

281280
@Test

0 commit comments

Comments
 (0)