Skip to content

Commit 58a2b79

Browse files
committed
Harmonize hint registration
Previously, a shortcut method for the default ExecutableMode was provided, but we found out that the shortcut makes it harder to determine the intent. This commit harmonizes hints registration for types, methods, and fields. An ExecutableMode is now mandatory to register a method or constructor. Previous methods that infer a mode or provided a customizer of the builder are deprecated. Closes gh-29135
1 parent c8f7a76 commit 58a2b79

File tree

14 files changed

+94
-162
lines changed

14 files changed

+94
-162
lines changed

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1007,7 +1007,7 @@ private CodeBlock generateMethodStatementForMethod(Method method,
10071007
AccessVisibility visibility = AccessVisibility.forMember(method);
10081008
if (visibility == AccessVisibility.PRIVATE
10091009
|| visibility == AccessVisibility.PROTECTED) {
1010-
hints.reflection().registerMethod(method);
1010+
hints.reflection().registerMethod(method, ExecutableMode.INVOKE);
10111011
code.add(".resolveAndInvoke($L, $L)", REGISTERED_BEAN_PARAMETER,
10121012
INSTANCE_PARAMETER);
10131013
}

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -145,7 +145,7 @@ private void addInitDestroyMethods(Builder code,
145145
private void addInitDestroyHint(Class<?> beanUserClass, String methodName) {
146146
Method method = ReflectionUtils.findMethod(beanUserClass, methodName);
147147
if (method != null) {
148-
this.hints.reflection().registerMethod(method);
148+
this.hints.reflection().registerMethod(method, ExecutableMode.INVOKE);
149149
}
150150
}
151151

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -147,7 +147,7 @@ private CodeBlock generateCodeForInaccessibleConstructor(String beanName,
147147
Class<?> beanClass, Constructor<?> constructor, boolean dependsOnBean) {
148148

149149
this.generationContext.getRuntimeHints().reflection()
150-
.registerConstructor(constructor);
150+
.registerConstructor(constructor, ExecutableMode.INVOKE);
151151
GeneratedMethod generatedMethod = generateGetInstanceSupplierMethod(method -> {
152152
method.addJavadoc("Get the bean instance supplier for '$L'.", beanName);
153153
method.addModifiers(PRIVATE_STATIC);
@@ -240,7 +240,7 @@ private CodeBlock generateCodeForInaccessibleFactoryMethod(String beanName, Clas
240240
Method factoryMethod, Class<?> declaringClass) {
241241

242242
this.generationContext.getRuntimeHints().reflection()
243-
.registerMethod(factoryMethod);
243+
.registerMethod(factoryMethod, ExecutableMode.INVOKE);
244244
GeneratedMethod getInstanceMethod = generateGetInstanceSupplierMethod(method -> {
245245
method.addJavadoc("Get the bean instance supplier for '$L'.", beanName);
246246
method.addModifiers(PRIVATE_STATIC);

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

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -194,7 +194,7 @@ void classGetConstructorsShouldNotMatchTypeReflectionHint() {
194194

195195
@Test
196196
void classGetConstructorsShouldMatchConstructorReflectionHint() throws Exception {
197-
hints.reflection().registerConstructor(String.class.getConstructor());
197+
hints.reflection().registerConstructor(String.class.getConstructor(), ExecutableMode.INVOKE);
198198
assertThatInvocationMatches(InstrumentedMethod.CLASS_GETCONSTRUCTORS, this.stringGetConstructors);
199199
}
200200

@@ -250,7 +250,7 @@ void classGetDeclaredConstructorsShouldNotMatchTypeReflectionHint() {
250250

251251
@Test
252252
void classGetDeclaredConstructorsShouldMatchConstructorReflectionHint() throws Exception {
253-
hints.reflection().registerConstructor(String.class.getConstructor());
253+
hints.reflection().registerConstructor(String.class.getConstructor(), ExecutableMode.INVOKE);
254254
assertThatInvocationMatches(InstrumentedMethod.CLASS_GETDECLAREDCONSTRUCTORS, this.stringGetDeclaredConstructors);
255255
}
256256

@@ -350,7 +350,7 @@ void classGetDeclaredMethodsShouldNotMatchTypeReflectionHint() {
350350

351351
@Test
352352
void classGetDeclaredMethodsShouldMatchMethodReflectionHint() throws Exception {
353-
hints.reflection().registerMethod(String.class.getMethod("toString"));
353+
hints.reflection().registerMethod(String.class.getMethod("toString"), ExecutableMode.INVOKE);
354354
assertThatInvocationMatches(InstrumentedMethod.CLASS_GETDECLAREDMETHODS, this.stringGetScaleMethod);
355355
}
356356

@@ -392,7 +392,7 @@ void classGetMethodsShouldNotMatchTypeReflectionHint() {
392392

393393
@Test
394394
void classGetMethodsShouldMatchMethodReflectionHint() throws Exception {
395-
hints.reflection().registerMethod(String.class.getMethod("toString"));
395+
hints.reflection().registerMethod(String.class.getMethod("toString"), ExecutableMode.INVOKE);
396396
assertThatInvocationMatches(InstrumentedMethod.CLASS_GETMETHODS, this.stringGetMethods);
397397
}
398398

spring-core/src/main/java/org/springframework/aot/hint/BindingReflectionHintsRegistrar.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -145,7 +145,7 @@ private void registerKotlinSerializationHints(ReflectionHints hints, Class<?> cl
145145
Class<?> companionClass = ClassUtils.resolveClassName(companionClassName, null);
146146
Method serializerMethod = ClassUtils.getMethodIfAvailable(companionClass, "serializer");
147147
if (serializerMethod != null) {
148-
hints.registerMethod(serializerMethod);
148+
hints.registerMethod(serializerMethod, ExecutableMode.INVOKE);
149149
}
150150
}
151151
}

spring-core/src/main/java/org/springframework/aot/hint/ReflectionHints.java

Lines changed: 42 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,8 @@
3636
* Gather the need for reflection at runtime.
3737
*
3838
* @author Stephane Nicoll
39+
* @author Phillip Webb
40+
* @author Andy Wilkinson
3941
* @since 6.0
4042
*/
4143
public class ReflectionHints {
@@ -79,6 +81,7 @@ public TypeHint getTypeHint(Class<?> type) {
7981
* @param type the type to customize
8082
* @param typeHint a builder to further customize hints for that type
8183
* @return {@code this}, to facilitate method chaining
84+
* @see #registerType(TypeReference, MemberCategory...)
8285
*/
8386
public ReflectionHints registerType(TypeReference type, Consumer<TypeHint.Builder> typeHint) {
8487
Builder builder = this.types.computeIfAbsent(type, TypeHint.Builder::new);
@@ -93,29 +96,30 @@ public ReflectionHints registerType(TypeReference type, Consumer<TypeHint.Builde
9396
* @param memberCategories the member categories to apply
9497
* @return {@code this}, to facilitate method chaining
9598
*/
96-
public ReflectionHints registerType(Class<?> type, MemberCategory... memberCategories) {
97-
return registerType(TypeReference.of(type), memberCategories);
99+
public ReflectionHints registerType(TypeReference type, MemberCategory... memberCategories) {
100+
return registerType(type, TypeHint.builtWith(memberCategories));
98101
}
99102

100103
/**
101-
* Register or customize reflection hints for the specified type
102-
* using the specified {@link MemberCategory MemberCategories}.
104+
* Register or customize reflection hints for the specified type.
103105
* @param type the type to customize
104-
* @param memberCategories the member categories to apply
106+
* @param typeHint a builder to further customize hints for that type
105107
* @return {@code this}, to facilitate method chaining
108+
* @see #registerType(Class, MemberCategory...)
106109
*/
107-
public ReflectionHints registerType(TypeReference type , MemberCategory... memberCategories) {
108-
return registerType(type, TypeHint.builtWith(memberCategories));
110+
public ReflectionHints registerType(Class<?> type, Consumer<TypeHint.Builder> typeHint) {
111+
return registerType(TypeReference.of(type), typeHint);
109112
}
110113

111114
/**
112-
* Register or customize reflection hints for the specified type.
115+
* Register or customize reflection hints for the specified type
116+
* using the specified {@link MemberCategory MemberCategories}.
113117
* @param type the type to customize
114-
* @param typeHint a builder to further customize hints for that type
118+
* @param memberCategories the member categories to apply
115119
* @return {@code this}, to facilitate method chaining
116120
*/
117-
public ReflectionHints registerType(Class<?> type, Consumer<TypeHint.Builder> typeHint) {
118-
return registerType(TypeReference.of(type), typeHint);
121+
public ReflectionHints registerType(Class<?> type, MemberCategory... memberCategories) {
122+
return registerType(TypeReference.of(type), memberCategories);
119123
}
120124

121125
/**
@@ -125,6 +129,7 @@ public ReflectionHints registerType(Class<?> type, Consumer<TypeHint.Builder> ty
125129
* @param typeName the type to customize
126130
* @param typeHint a builder to further customize hints for that type
127131
* @return {@code this}, to facilitate method chaining
132+
* @see #registerTypeIfPresent(ClassLoader, String, MemberCategory...)
128133
*/
129134
public ReflectionHints registerTypeIfPresent(@Nullable ClassLoader classLoader,
130135
String typeName, Consumer<TypeHint.Builder> typeHint) {
@@ -134,6 +139,19 @@ public ReflectionHints registerTypeIfPresent(@Nullable ClassLoader classLoader,
134139
return this;
135140
}
136141

142+
/**
143+
* Register or customize reflection hints for the specified type if it
144+
* is available using the specified {@link ClassLoader}.
145+
* @param classLoader the classloader to use to check if the type is present
146+
* @param typeName the type to customize
147+
* @param memberCategories the member categories to apply
148+
* @return {@code this}, to facilitate method chaining
149+
*/
150+
public ReflectionHints registerTypeIfPresent(@Nullable ClassLoader classLoader,
151+
String typeName, MemberCategory... memberCategories) {
152+
return registerTypeIfPresent(classLoader, typeName, TypeHint.builtWith(memberCategories));
153+
}
154+
137155
/**
138156
* Register or customize reflection hints for the types defined by the
139157
* specified list of {@link TypeReference type references}. The specified
@@ -162,7 +180,9 @@ public ReflectionHints registerField(Field field) {
162180
* enabling {@link ExecutableMode#INVOKE}.
163181
* @param constructor the constructor that requires reflection
164182
* @return {@code this}, to facilitate method chaining
183+
* @deprecated in favor of {@link #registerConstructor(Constructor, ExecutableMode)}
165184
*/
185+
@Deprecated
166186
public ReflectionHints registerConstructor(Constructor<?> constructor) {
167187
return registerConstructor(constructor, ExecutableMode.INVOKE);
168188
}
@@ -175,16 +195,19 @@ public ReflectionHints registerConstructor(Constructor<?> constructor) {
175195
* @return {@code this}, to facilitate method chaining
176196
*/
177197
public ReflectionHints registerConstructor(Constructor<?> constructor, ExecutableMode mode) {
178-
return registerConstructor(constructor, ExecutableHint.builtWith(mode));
198+
return registerType(TypeReference.of(constructor.getDeclaringClass()),
199+
typeHint -> typeHint.withConstructor(mapParameters(constructor), mode));
179200
}
180201

181202
/**
182203
* Register the need for reflection on the specified {@link Constructor}.
183204
* @param constructor the constructor that requires reflection
184205
* @param constructorHint a builder to further customize the hints of this
185206
* constructor
186-
* @return {@code this}, to facilitate method chaining
207+
* @return {@code this}, to facilitate method chaining`
208+
* @deprecated in favor of {@link #registerConstructor(Constructor, ExecutableMode)}
187209
*/
210+
@Deprecated
188211
public ReflectionHints registerConstructor(Constructor<?> constructor, Consumer<ExecutableHint.Builder> constructorHint) {
189212
return registerType(TypeReference.of(constructor.getDeclaringClass()),
190213
typeHint -> typeHint.withConstructor(mapParameters(constructor), constructorHint));
@@ -195,7 +218,9 @@ public ReflectionHints registerConstructor(Constructor<?> constructor, Consumer<
195218
* enabling {@link ExecutableMode#INVOKE}.
196219
* @param method the method that requires reflection
197220
* @return {@code this}, to facilitate method chaining
221+
* @deprecated in favor of {@link #registerMethod(Method, ExecutableMode)}
198222
*/
223+
@Deprecated
199224
public ReflectionHints registerMethod(Method method) {
200225
return registerMethod(method, ExecutableMode.INVOKE);
201226
}
@@ -208,15 +233,18 @@ public ReflectionHints registerMethod(Method method) {
208233
* @return {@code this}, to facilitate method chaining
209234
*/
210235
public ReflectionHints registerMethod(Method method, ExecutableMode mode) {
211-
return registerMethod(method, ExecutableHint.builtWith(mode));
236+
return registerType(TypeReference.of(method.getDeclaringClass()),
237+
typeHint -> typeHint.withMethod(method.getName(), mapParameters(method), mode));
212238
}
213239

214240
/**
215241
* Register the need for reflection on the specified {@link Method}.
216242
* @param method the method that requires reflection
217243
* @param methodHint a builder to further customize the hints of this method
218244
* @return {@code this}, to facilitate method chaining
245+
* @deprecated in favor of {@link #registerMethod(Method, ExecutableMode)}
219246
*/
247+
@Deprecated
220248
public ReflectionHints registerMethod(Method method, Consumer<ExecutableHint.Builder> methodHint) {
221249
return registerType(TypeReference.of(method.getDeclaringClass()),
222250
typeHint -> typeHint.withMethod(method.getName(), mapParameters(method), methodHint));

spring-core/src/main/java/org/springframework/aot/hint/TypeHint.java

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,8 @@
3535
* A hint that describes the need for reflection on a type.
3636
*
3737
* @author Stephane Nicoll
38+
* @author Phillip Webb
39+
* @author Andy Wilkinson
3840
* @since 6.0
3941
*/
4042
public final class TypeHint implements ConditionalHint {
@@ -199,7 +201,9 @@ public Builder withField(String name) {
199201
* parameter types, enabling {@link ExecutableMode#INVOKE}.
200202
* @param parameterTypes the parameter types of the constructor
201203
* @return {@code this}, to facilitate method chaining
204+
* @deprecated in favor of {@link #withConstructor(List, ExecutableMode)}
202205
*/
206+
@Deprecated
203207
public Builder withConstructor(List<TypeReference> parameterTypes) {
204208
return withConstructor(parameterTypes, ExecutableMode.INVOKE);
205209
}
@@ -222,8 +226,11 @@ public Builder withConstructor(List<TypeReference> parameterTypes, ExecutableMod
222226
* @param constructorHint a builder to further customize the hints of this
223227
* constructor
224228
* @return {@code this}, to facilitate method chaining
229+
* @deprecated in favor of {@link #withConstructor(List, ExecutableMode)}
225230
*/
226-
public Builder withConstructor(List<TypeReference> parameterTypes, Consumer<ExecutableHint.Builder> constructorHint) {
231+
@Deprecated
232+
public Builder withConstructor(List<TypeReference> parameterTypes,
233+
Consumer<ExecutableHint.Builder> constructorHint) {
227234
ExecutableKey key = new ExecutableKey("<init>", parameterTypes);
228235
ExecutableHint.Builder builder = this.constructors.computeIfAbsent(key,
229236
k -> ExecutableHint.ofConstructor(parameterTypes));
@@ -237,7 +244,9 @@ public Builder withConstructor(List<TypeReference> parameterTypes, Consumer<Exec
237244
* @param name the name of the method
238245
* @param parameterTypes the parameter types of the constructor
239246
* @return {@code this}, to facilitate method chaining
247+
* @deprecated in favor of {@link #withMethod(String, List, ExecutableMode)}
240248
*/
249+
@Deprecated
241250
public Builder withMethod(String name, List<TypeReference> parameterTypes) {
242251
return withMethod(name, parameterTypes, ExecutableMode.INVOKE);
243252
}
@@ -261,8 +270,11 @@ public Builder withMethod(String name, List<TypeReference> parameterTypes, Execu
261270
* @param parameterTypes the parameter types of the constructor
262271
* @param methodHint a builder to further customize the hints of this method
263272
* @return {@code this}, to facilitate method chaining
273+
* @deprecated in favor of {@link #withMethod(String, List, ExecutableMode)}
264274
*/
265-
public Builder withMethod(String name, List<TypeReference> parameterTypes, Consumer<ExecutableHint.Builder> methodHint) {
275+
@Deprecated
276+
public Builder withMethod(String name, List<TypeReference> parameterTypes,
277+
Consumer<ExecutableHint.Builder> methodHint) {
266278
ExecutableKey key = new ExecutableKey(name, parameterTypes);
267279
ExecutableHint.Builder builder = this.methods.computeIfAbsent(key,
268280
k -> ExecutableHint.ofMethod(name, parameterTypes));
@@ -274,6 +286,7 @@ public Builder withMethod(String name, List<TypeReference> parameterTypes, Consu
274286
* Adds the specified {@linkplain MemberCategory member categories}.
275287
* @param memberCategories the categories to apply
276288
* @return {@code this}, to facilitate method chaining
289+
* @see TypeHint#builtWith(MemberCategory...)
277290
*/
278291
public Builder withMembers(MemberCategory... memberCategories) {
279292
this.memberCategories.addAll(Arrays.asList(memberCategories));

spring-core/src/main/java/org/springframework/aot/hint/annotation/SimpleReflectiveProcessor.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
import java.lang.reflect.Field;
2222
import java.lang.reflect.Method;
2323

24+
import org.springframework.aot.hint.ExecutableMode;
2425
import org.springframework.aot.hint.ReflectionHints;
2526

2627
/**
@@ -64,7 +65,7 @@ protected void registerTypeHint(ReflectionHints hints, Class<?> type) {
6465
* @param constructor the constructor to process
6566
*/
6667
protected void registerConstructorHint(ReflectionHints hints, Constructor<?> constructor) {
67-
hints.registerConstructor(constructor);
68+
hints.registerConstructor(constructor, ExecutableMode.INVOKE);
6869
}
6970

7071
/**
@@ -82,7 +83,7 @@ protected void registerFieldHint(ReflectionHints hints, Field field) {
8283
* @param method the method to process
8384
*/
8485
protected void registerMethodHint(ReflectionHints hints, Method method) {
85-
hints.registerMethod(method);
86+
hints.registerMethod(method, ExecutableMode.INVOKE);
8687
}
8788

8889
}

0 commit comments

Comments
 (0)