Skip to content

Commit 8a61866

Browse files
committed
Harmonize registration of reflection hints
Closes gh-29011
2 parents 019785a + 7ca57b7 commit 8a61866

File tree

25 files changed

+543
-178
lines changed

25 files changed

+543
-178
lines changed

spring-beans/src/main/java/org/springframework/beans/factory/annotation/AutowiredAnnotationBeanPostProcessor.java

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,6 @@
4646
import org.springframework.aot.generate.GeneratedMethod;
4747
import org.springframework.aot.generate.GenerationContext;
4848
import org.springframework.aot.generate.MethodReference;
49-
import org.springframework.aot.hint.ExecutableHint;
5049
import org.springframework.aot.hint.ExecutableMode;
5150
import org.springframework.aot.hint.FieldHint;
5251
import org.springframework.aot.hint.RuntimeHints;
@@ -914,9 +913,6 @@ private static class AotContribution implements BeanRegistrationAotContribution
914913

915914
private static final String INSTANCE_PARAMETER = "instance";
916915

917-
private static final Consumer<ExecutableHint.Builder> INTROSPECT = builder -> builder
918-
.withMode(ExecutableMode.INTROSPECT);
919-
920916
private static final Consumer<FieldHint.Builder> ALLOW_WRITE = builder -> builder
921917
.allowWrite(true);
922918

@@ -1024,7 +1020,7 @@ private CodeBlock generateMethodStatementForMethod(Method method,
10241020
INSTANCE_PARAMETER);
10251021
}
10261022
else {
1027-
hints.reflection().registerMethod(method, INTROSPECT);
1023+
hints.reflection().registerMethod(method, ExecutableMode.INTROSPECT);
10281024
CodeBlock arguments = new AutowiredArgumentsCodeGenerator(this.target,
10291025
method).generateCode(method.getParameterTypes());
10301026
CodeBlock injectionCode = CodeBlock.of("args -> $L.$L($L)",

spring-beans/src/main/java/org/springframework/beans/factory/aot/BeanDefinitionPropertiesCodeGenerator.java

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -28,12 +28,10 @@
2828
import java.util.Objects;
2929
import java.util.function.BiFunction;
3030
import java.util.function.BiPredicate;
31-
import java.util.function.Consumer;
3231
import java.util.function.Function;
3332
import java.util.function.Predicate;
3433

3534
import org.springframework.aot.generate.GeneratedMethods;
36-
import org.springframework.aot.hint.ExecutableHint;
3735
import org.springframework.aot.hint.ExecutableMode;
3836
import org.springframework.aot.hint.RuntimeHints;
3937
import org.springframework.beans.BeanInfoFactory;
@@ -83,8 +81,6 @@ class BeanDefinitionPropertiesCodeGenerator {
8381

8482
private static final String BEAN_DEFINITION_VARIABLE = BeanRegistrationCodeFragments.BEAN_DEFINITION_VARIABLE;
8583

86-
private static final Consumer<ExecutableHint.Builder> INVOKE_HINT = hint -> hint.withMode(ExecutableMode.INVOKE);
87-
8884
private static final BeanInfoFactory beanInfoFactory = new ExtendedBeanInfoFactory();
8985

9086
private final RuntimeHints hints;
@@ -195,7 +191,7 @@ private void addPropertyValues(CodeBlock.Builder code,
195191
for (PropertyValue propertyValue : propertyValues) {
196192
Method writeMethod = writeMethods.get(propertyValue.getName());
197193
if (writeMethod != null) {
198-
this.hints.reflection().registerMethod(writeMethod, INVOKE_HINT);
194+
this.hints.reflection().registerMethod(writeMethod, ExecutableMode.INVOKE);
199195
}
200196
}
201197
}

spring-beans/src/main/java/org/springframework/beans/factory/aot/InstanceSupplierCodeGenerator.java

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,6 @@
2828
import org.springframework.aot.generate.GeneratedMethod;
2929
import org.springframework.aot.generate.GeneratedMethods;
3030
import org.springframework.aot.generate.GenerationContext;
31-
import org.springframework.aot.hint.ExecutableHint;
3231
import org.springframework.aot.hint.ExecutableMode;
3332
import org.springframework.beans.factory.support.InstanceSupplier;
3433
import org.springframework.beans.factory.support.RegisteredBean;
@@ -69,9 +68,6 @@ class InstanceSupplierCodeGenerator {
6968

7069
private static final CodeBlock NO_ARGS = CodeBlock.of("");
7170

72-
private static final Consumer<ExecutableHint.Builder> INTROSPECT = hint -> hint
73-
.withMode(ExecutableMode.INTROSPECT);
74-
7571

7672
private final GenerationContext generationContext;
7773

@@ -128,7 +124,7 @@ private CodeBlock generateCodeForAccessibleConstructor(String beanName, Class<?>
128124
Constructor<?> constructor, boolean dependsOnBean, Class<?> declaringClass) {
129125

130126
this.generationContext.getRuntimeHints().reflection()
131-
.registerConstructor(constructor, INTROSPECT);
127+
.registerConstructor(constructor, ExecutableMode.INTROSPECT);
132128
if (!dependsOnBean && constructor.getParameterCount() == 0) {
133129
if (!this.allowDirectSupplierShortcut) {
134130
return CodeBlock.of("$T.using($T::new)", InstanceSupplier.class,
@@ -225,7 +221,7 @@ private CodeBlock generateCodeForAccessibleFactoryMethod(String beanName,
225221
Class<?> beanClass, Method factoryMethod, Class<?> declaringClass, boolean dependsOnBean) {
226222

227223
this.generationContext.getRuntimeHints().reflection()
228-
.registerMethod(factoryMethod, INTROSPECT);
224+
.registerMethod(factoryMethod, ExecutableMode.INTROSPECT);
229225
if (!dependsOnBean && factoryMethod.getParameterCount() == 0) {
230226
CodeBlock.Builder code = CodeBlock.builder();
231227
code.add("$T.<$T>forFactoryMethod($T.class, $S)", BeanInstanceSupplier.class,

spring-beans/src/test/java/org/springframework/beans/factory/aot/InstanceSupplierCodeGeneratorTests.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -283,7 +283,7 @@ private ThrowingConsumer<TypeHint> hasMethodWithMode(ExecutableMode mode) {
283283
}
284284

285285
private ThrowingConsumer<ExecutableHint> hasMode(ExecutableMode mode) {
286-
return hint -> assertThat(hint.getModes()).containsExactly(mode);
286+
return hint -> assertThat(hint.getMode()).isEqualTo(mode);
287287
}
288288

289289
@SuppressWarnings("unchecked")

spring-context/src/main/java/org/springframework/context/aot/BindingReflectionHintsRegistrar.java

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -25,12 +25,10 @@
2525
import java.lang.reflect.Type;
2626
import java.util.LinkedHashSet;
2727
import java.util.Set;
28-
import java.util.function.Consumer;
2928

3029
import org.apache.commons.logging.Log;
3130
import org.apache.commons.logging.LogFactory;
3231

33-
import org.springframework.aot.hint.ExecutableHint;
3432
import org.springframework.aot.hint.ExecutableMode;
3533
import org.springframework.aot.hint.MemberCategory;
3634
import org.springframework.aot.hint.ReflectionHints;
@@ -54,9 +52,6 @@ public class BindingReflectionHintsRegistrar {
5452

5553
private static final Log logger = LogFactory.getLog(BindingReflectionHintsRegistrar.class);
5654

57-
private static final Consumer<ExecutableHint.Builder> INVOKE = builder -> builder
58-
.withMode(ExecutableMode.INVOKE);
59-
6055
private static final String KOTLIN_COMPANION_SUFFIX = "$Companion";
6156

6257
/**
@@ -127,7 +122,7 @@ private void registerReflectionHints(ReflectionHints hints, Set<Type> seen, Type
127122
}
128123

129124
private void registerRecordHints(ReflectionHints hints, Set<Type> seen, Method method) {
130-
hints.registerMethod(method, INVOKE);
125+
hints.registerMethod(method, ExecutableMode.INVOKE);
131126
MethodParameter methodParameter = MethodParameter.forExecutable(method, -1);
132127
Type methodParameterType = methodParameter.getGenericParameterType();
133128
if (!seen.contains(methodParameterType)) {
@@ -138,7 +133,7 @@ private void registerRecordHints(ReflectionHints hints, Set<Type> seen, Method m
138133
private void registerPropertyHints(ReflectionHints hints, Set<Type> seen, @Nullable Method method, int parameterIndex) {
139134
if (method != null && method.getDeclaringClass() != Object.class
140135
&& method.getDeclaringClass() != Enum.class) {
141-
hints.registerMethod(method, INVOKE);
136+
hints.registerMethod(method, ExecutableMode.INVOKE);
142137
MethodParameter methodParameter = MethodParameter.forExecutable(method, parameterIndex);
143138
Type methodParameterType = methodParameter.getGenericParameterType();
144139
if (!seen.contains(methodParameterType)) {

spring-context/src/test/java/org/springframework/context/aot/BindingReflectionHintsRegistrarTests.java

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ void registerTypeForSerializationWithGetter() {
7777
assertThat(typeHint.getType()).isEqualTo(TypeReference.of(SampleClassWithGetter.class));
7878
assertThat(typeHint.methods()).singleElement().satisfies(methodHint -> {
7979
assertThat(methodHint.getName()).isEqualTo("getName");
80-
assertThat(methodHint.getModes()).containsOnly(ExecutableMode.INVOKE);
80+
assertThat(methodHint.getMode()).isEqualTo(ExecutableMode.INVOKE);
8181
});
8282
});
8383
}
@@ -97,7 +97,7 @@ void registerTypeForSerializationWithSetter() {
9797
assertThat(typeHint.getType()).isEqualTo(TypeReference.of(SampleClassWithSetter.class));
9898
assertThat(typeHint.methods()).singleElement().satisfies(methodHint -> {
9999
assertThat(methodHint.getName()).isEqualTo("setName");
100-
assertThat(methodHint.getModes()).containsOnly(ExecutableMode.INVOKE);
100+
assertThat(methodHint.getMode()).isEqualTo(ExecutableMode.INVOKE);
101101
});
102102
});
103103
}
@@ -125,11 +125,11 @@ void registerTypeForSerializationWithListProperty() {
125125
assertThat(typeHint.methods()).satisfiesExactlyInAnyOrder(
126126
methodHint -> {
127127
assertThat(methodHint.getName()).isEqualTo("setNames");
128-
assertThat(methodHint.getModes()).containsOnly(ExecutableMode.INVOKE);
128+
assertThat(methodHint.getMode()).isEqualTo(ExecutableMode.INVOKE);
129129
},
130130
methodHint -> {
131131
assertThat(methodHint.getName()).isEqualTo("getNames");
132-
assertThat(methodHint.getModes()).containsOnly(ExecutableMode.INVOKE);
132+
assertThat(methodHint.getMode()).isEqualTo(ExecutableMode.INVOKE);
133133
});
134134
});
135135
}
@@ -180,7 +180,7 @@ void registerTypeForSerializationWithResolvableType() {
180180
assertThat(typeHint.methods()).singleElement().satisfies(
181181
methodHint -> {
182182
assertThat(methodHint.getName()).isEqualTo("getResolvableType");
183-
assertThat(methodHint.getModes()).containsOnly(ExecutableMode.INVOKE);
183+
assertThat(methodHint.getMode()).isEqualTo(ExecutableMode.INVOKE);
184184
});
185185
});
186186
}
@@ -218,7 +218,7 @@ void registerTypeForSerializationWithRecord() {
218218
assertThat(typeHint.getType()).isEqualTo(TypeReference.of(SampleRecord.class));
219219
assertThat(typeHint.methods()).singleElement().satisfies(methodHint -> {
220220
assertThat(methodHint.getName()).isEqualTo("name");
221-
assertThat(methodHint.getModes()).containsOnly(ExecutableMode.INVOKE);
221+
assertThat(methodHint.getMode()).isEqualTo(ExecutableMode.INVOKE);
222222
});
223223
});
224224
}

spring-context/src/test/kotlin/org/springframework/context/aot/KotlinBindingReflectionHintsRegistrarTests.kt

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -48,16 +48,15 @@ class KotlinBindingReflectionHintsRegistrarTests {
4848
assertThat(typeHint.methods()).singleElement()
4949
.satisfies(ThrowingConsumer { methodHint: ExecutableHint ->
5050
assertThat(methodHint.name).isEqualTo("getName")
51-
assertThat(methodHint.modes)
52-
.containsOnly(ExecutableMode.INVOKE)
51+
assertThat(methodHint.mode).isEqualTo(ExecutableMode.INVOKE)
5352
})
5453
},
5554
ThrowingConsumer { typeHint: TypeHint ->
5655
assertThat(typeHint.type).isEqualTo(TypeReference.of(SampleSerializableClass::class.qualifiedName + "\$Companion"))
5756
assertThat(typeHint.methods()).singleElement()
5857
.satisfies(ThrowingConsumer { methodHint: ExecutableHint ->
5958
assertThat(methodHint.name).isEqualTo("serializer")
60-
assertThat(methodHint.modes).containsOnly(ExecutableMode.INVOKE)
59+
assertThat(methodHint.mode).isEqualTo(ExecutableMode.INVOKE)
6160
})
6261
})
6362
}

spring-core-test/src/test/java/org/springframework/aot/agent/InstrumentedMethodTests.java

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -151,15 +151,15 @@ void classGetConstructorShouldMatchInvokeDeclaredConstructorsHint() {
151151

152152
@Test
153153
void classGetConstructorShouldMatchInstrospectConstructorHint() {
154-
hints.reflection().registerType(String.class, typeHint -> typeHint.withConstructor(Collections.emptyList(),
155-
constructorHint -> constructorHint.setModes(ExecutableMode.INTROSPECT)));
154+
hints.reflection().registerType(String.class,typeHint ->
155+
typeHint.withConstructor(Collections.emptyList(), ExecutableMode.INTROSPECT));
156156
assertThatInvocationMatches(InstrumentedMethod.CLASS_GETCONSTRUCTOR, this.stringGetConstructor);
157157
}
158158

159159
@Test
160160
void classGetConstructorShouldMatchInvokeConstructorHint() {
161-
hints.reflection().registerType(String.class, typeHint -> typeHint.withConstructor(Collections.emptyList(),
162-
constructorHint -> constructorHint.setModes(ExecutableMode.INVOKE)));
161+
hints.reflection().registerType(String.class, typeHint ->
162+
typeHint.withConstructor(Collections.emptyList(),ExecutableMode.INVOKE));
163163
assertThatInvocationMatches(InstrumentedMethod.CLASS_GETCONSTRUCTOR, this.stringGetConstructor);
164164
}
165165

@@ -201,15 +201,15 @@ void classGetDeclaredConstructorShouldNotMatchIntrospectPublicConstructorsHint()
201201

202202
@Test
203203
void classGetDeclaredConstructorShouldMatchInstrospectConstructorHint() {
204-
hints.reflection().registerType(String.class, typeHint -> typeHint.withConstructor(TypeReference.listOf(byte[].class, byte.class),
205-
constructorHint -> constructorHint.setModes(ExecutableMode.INTROSPECT)));
204+
hints.reflection().registerType(String.class, typeHint ->
205+
typeHint.withConstructor(TypeReference.listOf(byte[].class, byte.class), ExecutableMode.INTROSPECT));
206206
assertThatInvocationMatches(InstrumentedMethod.CLASS_GETDECLAREDCONSTRUCTOR, this.stringGetDeclaredConstructor);
207207
}
208208

209209
@Test
210210
void classGetDeclaredConstructorShouldMatchInvokeConstructorHint() {
211-
hints.reflection().registerType(String.class, typeHint -> typeHint.withConstructor(TypeReference.listOf(byte[].class, byte.class),
212-
constructorHint -> constructorHint.setModes(ExecutableMode.INVOKE)));
211+
hints.reflection().registerType(String.class, typeHint ->
212+
typeHint.withConstructor(TypeReference.listOf(byte[].class, byte.class), ExecutableMode.INVOKE));
213213
assertThatInvocationMatches(InstrumentedMethod.CLASS_GETDECLAREDCONSTRUCTOR, this.stringGetDeclaredConstructor);
214214
}
215215

@@ -237,7 +237,7 @@ void constructorNewInstanceShouldMatchInvokeHintOnConstructor() throws NoSuchMet
237237
RecordedInvocation invocation = RecordedInvocation.of(InstrumentedMethod.CONSTRUCTOR_NEWINSTANCE)
238238
.onInstance(String.class.getConstructor()).returnValue("").build();
239239
hints.reflection().registerType(String.class, typeHint ->
240-
typeHint.withConstructor(Collections.emptyList(), constructorHint -> constructorHint.withMode(ExecutableMode.INVOKE)));
240+
typeHint.withConstructor(Collections.emptyList(), ExecutableMode.INVOKE));
241241
assertThatInvocationMatches(InstrumentedMethod.CONSTRUCTOR_NEWINSTANCE, invocation);
242242
}
243243

@@ -246,7 +246,7 @@ void constructorNewInstanceShouldNotMatchIntrospectHintOnConstructor() throws No
246246
RecordedInvocation invocation = RecordedInvocation.of(InstrumentedMethod.CONSTRUCTOR_NEWINSTANCE)
247247
.onInstance(String.class.getConstructor()).returnValue("").build();
248248
hints.reflection().registerType(String.class, typeHint ->
249-
typeHint.withConstructor(Collections.emptyList(), constructorHint -> constructorHint.withMode(ExecutableMode.INTROSPECT)));
249+
typeHint.withConstructor(Collections.emptyList(), ExecutableMode.INTROSPECT));
250250
assertThatInvocationDoesNotMatch(InstrumentedMethod.CONSTRUCTOR_NEWINSTANCE, invocation);
251251
}
252252

@@ -285,15 +285,15 @@ void classGetDeclaredMethodShouldNotMatchIntrospectPublicMethodsHint() {
285285
void classGetDeclaredMethodShouldMatchIntrospectMethodHint() {
286286
List<TypeReference> parameterTypes = TypeReference.listOf(int.class, float.class);
287287
hints.reflection().registerType(String.class, typeHint ->
288-
typeHint.withMethod("scale", parameterTypes, methodHint -> methodHint.withMode(ExecutableMode.INTROSPECT)));
288+
typeHint.withMethod("scale", parameterTypes, ExecutableMode.INTROSPECT));
289289
assertThatInvocationMatches(InstrumentedMethod.CLASS_GETDECLAREDMETHOD, this.stringGetScaleMethod);
290290
}
291291

292292
@Test
293293
void classGetDeclaredMethodShouldMatchInvokeMethodHint() {
294294
List<TypeReference> parameterTypes = TypeReference.listOf(int.class, float.class);
295295
hints.reflection().registerType(String.class, typeHint ->
296-
typeHint.withMethod("scale", parameterTypes, methodHint -> methodHint.withMode(ExecutableMode.INVOKE)));
296+
typeHint.withMethod("scale", parameterTypes, ExecutableMode.INVOKE));
297297
assertThatInvocationMatches(InstrumentedMethod.CLASS_GETDECLAREDMETHOD, this.stringGetScaleMethod);
298298
}
299299

@@ -378,14 +378,14 @@ void classGetMethodShouldMatchInvokeDeclaredMethodsHint() {
378378
@Test
379379
void classGetMethodShouldMatchIntrospectMethodHint() {
380380
hints.reflection().registerType(String.class, typeHint ->
381-
typeHint.withMethod("toString", Collections.emptyList(), methodHint -> methodHint.setModes(ExecutableMode.INTROSPECT)));
381+
typeHint.withMethod("toString", Collections.emptyList(), ExecutableMode.INTROSPECT));
382382
assertThatInvocationMatches(InstrumentedMethod.CLASS_GETMETHOD, this.stringGetToStringMethod);
383383
}
384384

385385
@Test
386386
void classGetMethodShouldMatchInvokeMethodHint() {
387387
hints.reflection().registerType(String.class, typeHint ->
388-
typeHint.withMethod("toString", Collections.emptyList(), methodHint -> methodHint.setModes(ExecutableMode.INVOKE)));
388+
typeHint.withMethod("toString", Collections.emptyList(), ExecutableMode.INVOKE));
389389
assertThatInvocationMatches(InstrumentedMethod.CLASS_GETMETHOD, this.stringGetToStringMethod);
390390
}
391391

@@ -412,7 +412,7 @@ void methodInvokeShouldMatchInvokeHintOnMethod() throws NoSuchMethodException {
412412
RecordedInvocation invocation = RecordedInvocation.of(InstrumentedMethod.METHOD_INVOKE)
413413
.onInstance(String.class.getMethod("startsWith", String.class)).withArguments("testString", new Object[] { "test" }).build();
414414
hints.reflection().registerType(String.class, typeHint -> typeHint.withMethod("startsWith",
415-
TypeReference.listOf(String.class), methodHint -> methodHint.withMode(ExecutableMode.INVOKE)));
415+
TypeReference.listOf(String.class), ExecutableMode.INVOKE));
416416
assertThatInvocationMatches(InstrumentedMethod.METHOD_INVOKE, invocation);
417417
}
418418

@@ -421,7 +421,7 @@ void methodInvokeShouldNotMatchIntrospectHintOnMethod() throws NoSuchMethodExcep
421421
RecordedInvocation invocation = RecordedInvocation.of(InstrumentedMethod.METHOD_INVOKE)
422422
.onInstance(String.class.getMethod("toString")).withArguments("", new Object[0]).build();
423423
hints.reflection().registerType(String.class, typeHint ->
424-
typeHint.withMethod("toString", Collections.emptyList(), methodHint -> methodHint.withMode(ExecutableMode.INTROSPECT)));
424+
typeHint.withMethod("toString", Collections.emptyList(), ExecutableMode.INTROSPECT));
425425
assertThatInvocationDoesNotMatch(InstrumentedMethod.METHOD_INVOKE, invocation);
426426
}
427427

0 commit comments

Comments
 (0)