Skip to content

Commit 5f62d1d

Browse files
committed
Add className variants in ReflectionHintsPredicates
This commit adds predicates variants that accept `String className` instead of actual `Class<?>` when checking for fields and method hints. This is useful when the type under test is not visible from the current test class. Closes gh-29143
1 parent 198e17f commit 5f62d1d

File tree

2 files changed

+47
-0
lines changed

2 files changed

+47
-0
lines changed

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

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,23 @@ public MethodHintPredicate onMethod(Class<?> type, String methodName) {
114114
return new MethodHintPredicate(getMethod(type, methodName));
115115
}
116116

117+
/**
118+
* Return a predicate that checks whether a reflection hint is registered for the method that matches the given selector.
119+
* This looks up a method on the given type with the expected name, if unique.
120+
* By default, both introspection and invocation hints match.
121+
* <p>The returned type exposes additional methods that refine the predicate behavior.
122+
* @param className the name of the class holding the method
123+
* @param methodName the method name
124+
* @return the {@link RuntimeHints} predicate
125+
* @throws ClassNotFoundException if the class cannot be resolved.
126+
* @throws IllegalArgumentException if the method cannot be found or if multiple methods are found with the same name.
127+
*/
128+
public MethodHintPredicate onMethod(String className, String methodName) throws ClassNotFoundException {
129+
Assert.notNull(className, "'className' should not be null");
130+
Assert.hasText(methodName, "'methodName' should not be null");
131+
return onMethod(Class.forName(className), methodName);
132+
}
133+
117134
private Method getMethod(Class<?> type, String methodName) {
118135
ReflectionUtils.MethodFilter selector = method -> methodName.equals(method.getName());
119136
Set<Method> methods = MethodIntrospector.selectMethods(type, selector);
@@ -148,6 +165,23 @@ public FieldHintPredicate onField(Class<?> type, String fieldName) {
148165
return new FieldHintPredicate(field);
149166
}
150167

168+
/**
169+
* Return a predicate that checks whether a reflection hint is registered for the field that matches the given selector.
170+
* This looks up a field on the given type with the expected name, if present.
171+
* By default, unsafe or write access are not considered.
172+
* <p>The returned type exposes additional methods that refine the predicate behavior.
173+
* @param className the name of the class holding the field
174+
* @param fieldName the field name
175+
* @return the {@link RuntimeHints} predicate
176+
* @throws ClassNotFoundException if the class cannot be resolved.
177+
* @throws IllegalArgumentException if a field cannot be found with the given name.
178+
*/
179+
public FieldHintPredicate onField(String className, String fieldName) throws ClassNotFoundException {
180+
Assert.notNull(className, "'className' should not be null");
181+
Assert.hasText(fieldName, "'fieldName' should not be empty");
182+
return onField(Class.forName(className), fieldName);
183+
}
184+
151185
/**
152186
* Return a predicate that checks whether a reflection hint is registered for the given field.
153187
* By default, unsafe or write access are not considered.

spring-core/src/test/java/org/springframework/aot/hint/predicate/ReflectionHintsPredicatesTests.java

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333

3434
import static org.assertj.core.api.Assertions.assertThat;
3535
import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;
36+
import static org.assertj.core.api.Assertions.assertThatThrownBy;
3637

3738
/**
3839
* Tests for {@link ReflectionHintsPredicates}
@@ -319,6 +320,12 @@ void methodIntrospectionMatchesMethodHint() {
319320
assertPredicateMatches(reflection.onMethod(SampleClass.class, "publicMethod").introspect());
320321
}
321322

323+
@Test
324+
void methodIntrospectionFailsForUnknownType() {
325+
assertThatThrownBy(() -> reflection.onMethod("com.example.DoesNotExist", "publicMethod").introspect())
326+
.isInstanceOf(ClassNotFoundException.class);
327+
}
328+
322329
@Test
323330
void methodIntrospectionMatchesIntrospectPublicMethods() {
324331
runtimeHints.reflection().registerType(SampleClass.class, MemberCategory.INTROSPECT_PUBLIC_METHODS);
@@ -472,6 +479,12 @@ void shouldFailForMissingField() {
472479
assertThatIllegalArgumentException().isThrownBy(() -> reflection.onField(SampleClass.class, "missingField"));
473480
}
474481

482+
@Test
483+
void shouldFailForUnknownClass() {
484+
assertThatThrownBy(() -> reflection.onField("com.example.DoesNotExist", "missingField"))
485+
.isInstanceOf(ClassNotFoundException.class);
486+
}
487+
475488
@Test
476489
void fieldReflectionMatchesFieldHint() {
477490
runtimeHints.reflection().registerType(SampleClass.class, typeHint -> typeHint.withField("publicField"));

0 commit comments

Comments
 (0)