Skip to content

Commit 86a85f5

Browse files
committed
Fix introspection of annotations that use local aliased attributes
Closes gh-28528
1 parent 9e1d005 commit 86a85f5

File tree

2 files changed

+39
-9
lines changed

2 files changed

+39
-9
lines changed

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

Lines changed: 17 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818

1919
import java.lang.annotation.Annotation;
2020
import java.lang.reflect.Method;
21+
import java.util.HashSet;
2122
import java.util.LinkedHashSet;
2223
import java.util.Set;
2324
import java.util.function.Consumer;
@@ -55,24 +56,31 @@ public abstract class RuntimeHintsUtils {
5556
* @see SynthesizedAnnotation
5657
*/
5758
public static void registerAnnotation(RuntimeHints hints, Class<?> annotationType) {
59+
hints.reflection().registerType(annotationType, ANNOTATION_HINT);
5860
Set<Class<?>> allAnnotations = new LinkedHashSet<>();
59-
allAnnotations.add(annotationType);
60-
collectAliasedAnnotations(allAnnotations, annotationType);
61+
collectAliasedAnnotations(new HashSet<>(), allAnnotations, annotationType);
6162
allAnnotations.forEach(annotation -> hints.reflection().registerType(annotation, ANNOTATION_HINT));
62-
if (allAnnotations.size() > 1) {
63+
if (allAnnotations.size() > 0) {
6364
hints.proxies().registerJdkProxy(annotationType, SynthesizedAnnotation.class);
6465
}
6566
}
6667

67-
private static void collectAliasedAnnotations(Set<Class<?>> types, Class<?> annotationType) {
68+
private static void collectAliasedAnnotations(Set<Class<?>> seen, Set<Class<?>> types, Class<?> annotationType) {
69+
if (seen.contains(annotationType)) {
70+
return;
71+
}
72+
seen.add(annotationType);
6873
for (Method method : annotationType.getDeclaredMethods()) {
6974
MergedAnnotations methodAnnotations = MergedAnnotations.from(method);
7075
if (methodAnnotations.isPresent(AliasFor.class)) {
71-
Class<?> aliasedAnnotation = methodAnnotations.get(AliasFor.class).getClass("annotation");
72-
boolean process = (aliasedAnnotation != Annotation.class && !types.contains(aliasedAnnotation));
73-
if (process) {
74-
types.add(aliasedAnnotation);
75-
collectAliasedAnnotations(types, aliasedAnnotation);
76+
Class<?> annotationAttribute = methodAnnotations.get(AliasFor.class).getClass("annotation");
77+
Class<?> targetAnnotation = (annotationAttribute != Annotation.class
78+
? annotationAttribute : annotationType);
79+
if (!types.contains(targetAnnotation)) {
80+
types.add(targetAnnotation);
81+
if (!targetAnnotation.equals(annotationType)) {
82+
collectAliasedAnnotations(seen, types, targetAnnotation);
83+
}
7684
}
7785
}
7886
}

spring-core/src/test/java/org/springframework/aot/hint/support/RuntimeHintsUtilsTests.java

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,15 @@ void registerAnnotationType() {
5353
assertThat(this.hints.proxies().jdkProxies()).isEmpty();
5454
}
5555

56+
@Test
57+
void registerAnnotationTypeWithLocalUseOfAliasForRegistersProxy() {
58+
RuntimeHintsUtils.registerAnnotation(this.hints, LocalMapping.class);
59+
assertThat(this.hints.reflection().typeHints()).singleElement()
60+
.satisfies(annotationHint(LocalMapping.class));
61+
assertThat(this.hints.proxies().jdkProxies()).singleElement()
62+
.satisfies(annotationProxy(LocalMapping.class));
63+
}
64+
5665
@Test
5766
void registerAnnotationTypeProxyRegistersJdkProxy() {
5867
RuntimeHintsUtils.registerAnnotation(this.hints, RetryInvoker.class);
@@ -108,6 +117,19 @@ static class RetryWithEnabledFlagInvokerClass {
108117

109118
}
110119

120+
@Target({ ElementType.TYPE, ElementType.ANNOTATION_TYPE })
121+
@Retention(RetentionPolicy.RUNTIME)
122+
@Documented
123+
@interface LocalMapping {
124+
125+
@AliasFor("retries")
126+
int value() default 0;
127+
128+
@AliasFor("value")
129+
int retries() default 0;
130+
131+
}
132+
111133

112134
@Target({ ElementType.TYPE, ElementType.ANNOTATION_TYPE })
113135
@Retention(RetentionPolicy.RUNTIME)

0 commit comments

Comments
 (0)