Support arbitrary levels of meta-annotations in TypeDescriptor

Prior to this commit, the `getAnnotation()` method in `TypeDescriptor`
only supported a single level of meta-annotations. In other words, the
annotation hierarchy would not be exhaustively searched.

This commit provides support for arbitrary levels of meta-annotations
in `TypeDescriptor` by delegating to `AnnotationUtils.findAnnotation()`
within `TypeDescriptor.getAnnotation()`.

Issue: SPR-12793
This commit is contained in:
Sam Brannen
2015-05-08 16:05:18 +02:00
parent 5f03c97295
commit 04d6afe54d
2 changed files with 58 additions and 7 deletions

View File

@@ -27,6 +27,7 @@ import java.util.stream.Stream;
import org.springframework.core.MethodParameter;
import org.springframework.core.ResolvableType;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.lang.UsesJava8;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
@@ -237,6 +238,8 @@ public class TypeDescriptor implements Serializable {
/**
* Determine if this type descriptor has the specified annotation.
* <p>As of Spring Framework 4.2, this method supports arbitrary levels
* of meta-annotations.
* @param annotationType the annotation type
* @return <tt>true</tt> if the annotation is present
*/
@@ -245,19 +248,27 @@ public class TypeDescriptor implements Serializable {
}
/**
* Obtain the annotation associated with this type descriptor of the specified type.
* Obtain the annotation of the specified {@code annotationType} that is
* on this type descriptor.
* <p>As of Spring Framework 4.2, this method supports arbitrary levels
* of meta-annotations.
* @param annotationType the annotation type
* @return the annotation, or {@code null} if no such annotation exists on this type descriptor
*/
@SuppressWarnings("unchecked")
public <T extends Annotation> T getAnnotation(Class<T> annotationType) {
// Search in annotations that are "present" (i.e., locally declared or inherited)
//
// NOTE: this unfortunately favors inherited annotations over locally declared composed annotations.
for (Annotation annotation : getAnnotations()) {
if (annotation.annotationType().equals(annotationType)) {
return (T) annotation;
}
}
for (Annotation metaAnn : getAnnotations()) {
T ann = metaAnn.annotationType().getAnnotation(annotationType);
// Search in annotation hierarchy
for (Annotation composedAnnotation : getAnnotations()) {
T ann = AnnotationUtils.findAnnotation(composedAnnotation.annotationType(), annotationType);
if (ann != null) {
return ann;
}