Polish AnnotationUtils
- Added explicit reference to “get” and “find” lookup types in the class-level Javadoc. - Updated documentation for the underlying algorithms in findAnnotation(Method,Class) and findAnnotation(Class,Class) in line with the status quo. - Reverted recent changes to findAnnotationDeclaringClass() by removing meta-annotation support in order to maintain backwards compatibility with previous releases.
This commit is contained in:
parent
665251fa2f
commit
a613126be0
|
|
@ -34,16 +34,19 @@ import org.springframework.util.ObjectUtils;
|
|||
import org.springframework.util.ReflectionUtils;
|
||||
|
||||
/**
|
||||
* General utility methods for working with annotations, handling bridge methods (which the compiler
|
||||
* generates for generic declarations) as well as super methods (for optional "annotation inheritance").
|
||||
* Note that none of this is provided by the JDK's introspection facilities themselves.
|
||||
* General utility methods for working with annotations, handling bridge methods
|
||||
* (which the compiler generates for generic declarations) as well as super methods
|
||||
* (for optional "annotation inheritance"). Note that none of this is
|
||||
* provided by the JDK's introspection facilities themselves.
|
||||
*
|
||||
* <p>As a general rule for runtime-retained annotations (e.g. for transaction control, authorization or service
|
||||
* exposure), always use the lookup methods on this class (e.g., {@link #findAnnotation(Method, Class)}, {@link
|
||||
* #getAnnotation(Method, Class)}, and {@link #getAnnotations(Method)}) instead of the plain annotation lookup
|
||||
* methods in the JDK. You can still explicitly choose between lookup on the given class level only ({@link
|
||||
* #getAnnotation(Method, Class)}) and lookup in the entire inheritance hierarchy of the given method ({@link
|
||||
* #findAnnotation(Method, Class)}).
|
||||
* <p>As a general rule for runtime-retained annotations (e.g. for transaction
|
||||
* control, authorization, or service exposure), always use the lookup methods
|
||||
* on this class (e.g., {@link #findAnnotation(Method, Class)},
|
||||
* {@link #getAnnotation(Method, Class)}, and {@link #getAnnotations(Method)})
|
||||
* instead of the plain annotation lookup methods in the JDK. You can still
|
||||
* explicitly choose between a <em>get</em> lookup on the given class level only
|
||||
* ({@link #getAnnotation(Method, Class)}) and a <em>find</em> lookup in the entire
|
||||
* inheritance hierarchy of the given method ({@link #findAnnotation(Method, Class)}).
|
||||
*
|
||||
* @author Rob Harrop
|
||||
* @author Juergen Hoeller
|
||||
|
|
@ -165,9 +168,11 @@ public abstract class AnnotationUtils {
|
|||
}
|
||||
|
||||
/**
|
||||
* Get a single {@link Annotation} of {@code annotationType} from the supplied {@link Method},
|
||||
* traversing its super methods if no annotation can be found on the given method itself.
|
||||
* <p>Annotations on methods are not inherited by default, so we need to handle this explicitly.
|
||||
* Find a single {@link Annotation} of {@code annotationType} from the supplied
|
||||
* {@link Method}, traversing its super methods (i.e., from super classes and
|
||||
* interfaces) if no annotation can be found on the given method itself.
|
||||
* <p>Annotations on methods are not inherited by default, so we need to handle
|
||||
* this explicitly.
|
||||
* @param method the method to look for annotations on
|
||||
* @param annotationType the annotation class to look for
|
||||
* @return the annotation found, or {@code null} if none found
|
||||
|
|
@ -235,16 +240,23 @@ public abstract class AnnotationUtils {
|
|||
}
|
||||
|
||||
/**
|
||||
* Find a single {@link Annotation} of {@code annotationType} from the supplied {@link Class},
|
||||
* traversing its interfaces and superclasses if no annotation can be found on the given class itself.
|
||||
* <p>This method explicitly handles class-level annotations which are not declared as
|
||||
* {@link java.lang.annotation.Inherited inherited} <i>as well as annotations on interfaces</i>.
|
||||
* <p>The algorithm operates as follows: Searches for an annotation on the given class and returns
|
||||
* it if found. Else searches all interfaces that the given class declares, returning the annotation
|
||||
* from the first matching candidate, if any. Else proceeds with introspection of the superclass
|
||||
* of the given class, checking the superclass itself; if no annotation found there, proceeds
|
||||
* with the interfaces that the superclass declares. Recursing up through the entire superclass
|
||||
* hierarchy if no match is found.
|
||||
* Find a single {@link Annotation} of {@code annotationType} from the supplied
|
||||
* {@link Class}, traversing its annotations, interfaces, and superclasses if
|
||||
* no annotation can be found on the given class itself.
|
||||
* <p>This method explicitly handles class-level annotations which are not
|
||||
* declared as {@link java.lang.annotation.Inherited inherited} <i>as well
|
||||
* as meta-annotations and annotations on interfaces</i>.
|
||||
* <p>The algorithm operates as follows:
|
||||
* <ol>
|
||||
* <li>Search for an annotation on the given class and return it if found.
|
||||
* <li>Recursively search through all interfaces that the given class
|
||||
* declares, returning the annotation from the first matching candidate, if any.
|
||||
* <li>Recursively search through all annotations that the given class
|
||||
* declares, returning the annotation from the first matching candidate, if any.
|
||||
* <li>Proceed with introspection of the superclass hierarchy of the given
|
||||
* class by returning to step #1 with the superclass as the class to look for
|
||||
* annotations on.
|
||||
* </ol>
|
||||
* @param clazz the class to look for annotations on
|
||||
* @param annotationType the annotation class to look for
|
||||
* @return the annotation found, or {@code null} if none found
|
||||
|
|
@ -301,23 +313,9 @@ public abstract class AnnotationUtils {
|
|||
if (clazz == null || clazz.equals(Object.class)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Declared locally?
|
||||
if (isAnnotationDeclaredLocally(annotationType, clazz)) {
|
||||
return clazz;
|
||||
}
|
||||
|
||||
// Declared on a stereotype annotation (i.e., as a meta-annotation)?
|
||||
if (!Annotation.class.isAssignableFrom(clazz)) {
|
||||
for (Annotation stereotype : clazz.getAnnotations()) {
|
||||
Class<?> declaringClass = findAnnotationDeclaringClass(annotationType, stereotype.annotationType());
|
||||
if (declaringClass != null) {
|
||||
return declaringClass;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Declared on a superclass?
|
||||
return findAnnotationDeclaringClass(annotationType, clazz.getSuperclass());
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue