Browse Source

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.
pull/418/head
Sam Brannen 12 years ago
parent
commit
a613126be0
  1. 70
      spring-core/src/main/java/org/springframework/core/annotation/AnnotationUtils.java

70
spring-core/src/main/java/org/springframework/core/annotation/AnnotationUtils.java

@ -34,16 +34,19 @@ import org.springframework.util.ObjectUtils;
import org.springframework.util.ReflectionUtils; import org.springframework.util.ReflectionUtils;
/** /**
* General utility methods for working with annotations, handling bridge methods (which the compiler * General utility methods for working with annotations, handling bridge methods
* generates for generic declarations) as well as super methods (for optional "annotation inheritance"). * (which the compiler generates for generic declarations) as well as super methods
* Note that none of this is provided by the JDK's introspection facilities themselves. * (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 * <p>As a general rule for runtime-retained annotations (e.g. for transaction
* exposure), always use the lookup methods on this class (e.g., {@link #findAnnotation(Method, Class)}, {@link * control, authorization, or service exposure), always use the lookup methods
* #getAnnotation(Method, Class)}, and {@link #getAnnotations(Method)}) instead of the plain annotation lookup * on this class (e.g., {@link #findAnnotation(Method, Class)},
* methods in the JDK. You can still explicitly choose between lookup on the given class level only ({@link * {@link #getAnnotation(Method, Class)}, and {@link #getAnnotations(Method)})
* #getAnnotation(Method, Class)}) and lookup in the entire inheritance hierarchy of the given method ({@link * instead of the plain annotation lookup methods in the JDK. You can still
* #findAnnotation(Method, Class)}). * 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 Rob Harrop
* @author Juergen Hoeller * @author Juergen Hoeller
@ -165,9 +168,11 @@ public abstract class AnnotationUtils {
} }
/** /**
* Get a single {@link Annotation} of {@code annotationType} from the supplied {@link Method}, * Find a single {@link Annotation} of {@code annotationType} from the supplied
* traversing its super methods if no annotation can be found on the given method itself. * {@link Method}, traversing its super methods (i.e., from super classes and
* <p>Annotations on methods are not inherited by default, so we need to handle this explicitly. * 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 method the method to look for annotations on
* @param annotationType the annotation class to look for * @param annotationType the annotation class to look for
* @return the annotation found, or {@code null} if none found * @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}, * Find a single {@link Annotation} of {@code annotationType} from the supplied
* traversing its interfaces and superclasses if no annotation can be found on the given class itself. * {@link Class}, traversing its annotations, interfaces, and superclasses if
* <p>This method explicitly handles class-level annotations which are not declared as * no annotation can be found on the given class itself.
* {@link java.lang.annotation.Inherited inherited} <i>as well as annotations on interfaces</i>. * <p>This method explicitly handles class-level annotations which are not
* <p>The algorithm operates as follows: Searches for an annotation on the given class and returns * declared as {@link java.lang.annotation.Inherited inherited} <i>as well
* it if found. Else searches all interfaces that the given class declares, returning the annotation * as meta-annotations and annotations on interfaces</i>.
* from the first matching candidate, if any. Else proceeds with introspection of the superclass * <p>The algorithm operates as follows:
* of the given class, checking the superclass itself; if no annotation found there, proceeds * <ol>
* with the interfaces that the superclass declares. Recursing up through the entire superclass * <li>Search for an annotation on the given class and return it if found.
* hierarchy if no match is 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 clazz the class to look for annotations on
* @param annotationType the annotation class to look for * @param annotationType the annotation class to look for
* @return the annotation found, or {@code null} if none found * @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)) { if (clazz == null || clazz.equals(Object.class)) {
return null; return null;
} }
// Declared locally?
if (isAnnotationDeclaredLocally(annotationType, clazz)) { if (isAnnotationDeclaredLocally(annotationType, clazz)) {
return 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()); return findAnnotationDeclaringClass(annotationType, clazz.getSuperclass());
} }

Loading…
Cancel
Save