Browse Source

Fix introspection of annotations that use local aliased attributes

Closes gh-28528
pull/28538/head
Stephane Nicoll 3 years ago
parent
commit
86a85f558c
  1. 26
      spring-core/src/main/java/org/springframework/aot/hint/support/RuntimeHintsUtils.java
  2. 22
      spring-core/src/test/java/org/springframework/aot/hint/support/RuntimeHintsUtilsTests.java

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

@ -18,6 +18,7 @@ package org.springframework.aot.hint.support; @@ -18,6 +18,7 @@ package org.springframework.aot.hint.support;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.Set;
import java.util.function.Consumer;
@ -55,24 +56,31 @@ public abstract class RuntimeHintsUtils { @@ -55,24 +56,31 @@ public abstract class RuntimeHintsUtils {
* @see SynthesizedAnnotation
*/
public static void registerAnnotation(RuntimeHints hints, Class<?> annotationType) {
hints.reflection().registerType(annotationType, ANNOTATION_HINT);
Set<Class<?>> allAnnotations = new LinkedHashSet<>();
allAnnotations.add(annotationType);
collectAliasedAnnotations(allAnnotations, annotationType);
collectAliasedAnnotations(new HashSet<>(), allAnnotations, annotationType);
allAnnotations.forEach(annotation -> hints.reflection().registerType(annotation, ANNOTATION_HINT));
if (allAnnotations.size() > 1) {
if (allAnnotations.size() > 0) {
hints.proxies().registerJdkProxy(annotationType, SynthesizedAnnotation.class);
}
}
private static void collectAliasedAnnotations(Set<Class<?>> types, Class<?> annotationType) {
private static void collectAliasedAnnotations(Set<Class<?>> seen, Set<Class<?>> types, Class<?> annotationType) {
if (seen.contains(annotationType)) {
return;
}
seen.add(annotationType);
for (Method method : annotationType.getDeclaredMethods()) {
MergedAnnotations methodAnnotations = MergedAnnotations.from(method);
if (methodAnnotations.isPresent(AliasFor.class)) {
Class<?> aliasedAnnotation = methodAnnotations.get(AliasFor.class).getClass("annotation");
boolean process = (aliasedAnnotation != Annotation.class && !types.contains(aliasedAnnotation));
if (process) {
types.add(aliasedAnnotation);
collectAliasedAnnotations(types, aliasedAnnotation);
Class<?> annotationAttribute = methodAnnotations.get(AliasFor.class).getClass("annotation");
Class<?> targetAnnotation = (annotationAttribute != Annotation.class
? annotationAttribute : annotationType);
if (!types.contains(targetAnnotation)) {
types.add(targetAnnotation);
if (!targetAnnotation.equals(annotationType)) {
collectAliasedAnnotations(seen, types, targetAnnotation);
}
}
}
}

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

@ -53,6 +53,15 @@ class RuntimeHintsUtilsTests { @@ -53,6 +53,15 @@ class RuntimeHintsUtilsTests {
assertThat(this.hints.proxies().jdkProxies()).isEmpty();
}
@Test
void registerAnnotationTypeWithLocalUseOfAliasForRegistersProxy() {
RuntimeHintsUtils.registerAnnotation(this.hints, LocalMapping.class);
assertThat(this.hints.reflection().typeHints()).singleElement()
.satisfies(annotationHint(LocalMapping.class));
assertThat(this.hints.proxies().jdkProxies()).singleElement()
.satisfies(annotationProxy(LocalMapping.class));
}
@Test
void registerAnnotationTypeProxyRegistersJdkProxy() {
RuntimeHintsUtils.registerAnnotation(this.hints, RetryInvoker.class);
@ -108,6 +117,19 @@ class RuntimeHintsUtilsTests { @@ -108,6 +117,19 @@ class RuntimeHintsUtilsTests {
}
@Target({ ElementType.TYPE, ElementType.ANNOTATION_TYPE })
@Retention(RetentionPolicy.RUNTIME)
@Documented
@interface LocalMapping {
@AliasFor("retries")
int value() default 0;
@AliasFor("value")
int retries() default 0;
}
@Target({ ElementType.TYPE, ElementType.ANNOTATION_TYPE })
@Retention(RetentionPolicy.RUNTIME)

Loading…
Cancel
Save