Register annotation based on its type

This commit improves registerAnnotation to use the annotation type
rather than a `MergedAnnotation` attribute.

See gh-28497
This commit is contained in:
Stephane Nicoll
2022-05-25 10:25:53 +02:00
parent a60e9d6695
commit 059b66bf26
6 changed files with 56 additions and 41 deletions

View File

@@ -16,13 +16,18 @@
package org.springframework.aot.hint.support;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.util.LinkedHashSet;
import java.util.Set;
import java.util.function.Consumer;
import org.springframework.aot.hint.MemberCategory;
import org.springframework.aot.hint.RuntimeHints;
import org.springframework.aot.hint.TypeHint;
import org.springframework.aot.hint.TypeHint.Builder;
import org.springframework.core.annotation.MergedAnnotation;
import org.springframework.core.annotation.AliasFor;
import org.springframework.core.annotation.MergedAnnotations;
import org.springframework.core.annotation.SynthesizedAnnotation;
/**
@@ -38,24 +43,38 @@ public abstract class RuntimeHintsUtils {
* that its attributes are visible.
*/
public static final Consumer<Builder> ANNOTATION_HINT = hint ->
hint.withMembers(MemberCategory.INVOKE_PUBLIC_METHODS);
hint.withMembers(MemberCategory.INVOKE_DECLARED_METHODS);
/**
* Register the necessary hints so that the specified annotation is visible
* at runtime.
* at runtime. If an annotation attributes aliases an attribute of another
* annotation, it is registered as well and a JDK proxy hints is defined
* so that the synthesized annotation can be resolved.
* @param hints the {@link RuntimeHints} instance ot use
* @param annotation the annotation
* @param annotationType the annotation type
* @see SynthesizedAnnotation
*/
public static void registerAnnotation(RuntimeHints hints, MergedAnnotation<?> annotation) {
hints.reflection().registerType(annotation.getType(), ANNOTATION_HINT);
MergedAnnotation<?> parentSource = annotation.getMetaSource();
while (parentSource != null) {
hints.reflection().registerType(parentSource.getType(), ANNOTATION_HINT);
parentSource = parentSource.getMetaSource();
public static void registerAnnotation(RuntimeHints hints, Class<?> annotationType) {
Set<Class<?>> allAnnotations = new LinkedHashSet<>();
allAnnotations.add(annotationType);
collectAliasedAnnotations(allAnnotations, annotationType);
allAnnotations.forEach(annotation -> hints.reflection().registerType(annotation, ANNOTATION_HINT));
if (allAnnotations.size() > 1) {
hints.proxies().registerJdkProxy(annotationType, SynthesizedAnnotation.class);
}
if (annotation.synthesize() instanceof SynthesizedAnnotation) {
hints.proxies().registerJdkProxy(annotation.getType(), SynthesizedAnnotation.class);
}
private static void collectAliasedAnnotations(Set<Class<?>> types, Class<?> 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);
}
}
}
}

View File

@@ -16,9 +16,12 @@
package org.springframework.core.annotation;
import java.util.stream.Stream;
import org.springframework.aot.hint.RuntimeHints;
import org.springframework.aot.hint.RuntimeHintsRegistrar;
import org.springframework.aot.hint.support.RuntimeHintsUtils;
import org.springframework.lang.Nullable;
/**
* {@link RuntimeHintsRegistrar} for core annotations.
@@ -29,9 +32,9 @@ import org.springframework.aot.hint.support.RuntimeHintsUtils;
class CoreAnnotationsRuntimeHintsRegistrar implements RuntimeHintsRegistrar {
@Override
public void registerHints(RuntimeHints hints, ClassLoader classLoader) {
hints.reflection().registerType(AliasFor.class, RuntimeHintsUtils.ANNOTATION_HINT)
.registerType(Order.class, RuntimeHintsUtils.ANNOTATION_HINT);
public void registerHints(RuntimeHints hints, @Nullable ClassLoader classLoader) {
Stream.of(AliasFor.class, Order.class).forEach(annotationType ->
RuntimeHintsUtils.registerAnnotation(hints, annotationType));
}
}