Browse Source

Document "present" terminology in AnnotationUtils

Prior to this commit, the documentation in AnnotationUtils was
inconsistent, and at times even misleading, with regard to finding
annotations that are "present" or "directly present" on annotated
elements.

This commit defines the terminology used within AnnotationUtils and
introduces the explicit notion of "meta-present" to denote that
annotations are present within annotation hierarchies above annotated
elements.

Issue: SPR-13030
pull/763/merge
Sam Brannen 10 years ago
parent
commit
477d4c5126
  1. 177
      spring-core/src/main/java/org/springframework/core/annotation/AnnotationUtils.java

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

@ -54,12 +54,20 @@ import org.springframework.util.StringUtils; @@ -54,12 +54,20 @@ import org.springframework.util.StringUtils;
* ({@link #getAnnotation(Method, Class)}) and a <em>find</em> lookup in the entire
* inheritance hierarchy of the given method ({@link #findAnnotation(Method, Class)}).
*
* <h3>Terminology</h3>
* The terms <em>directly present</em> and <em>present</em> have the same
* meanings as defined in the class-level Javadoc for {@link AnnotatedElement}.
*
* <p>An annotation is <em>meta-present</em> on an element if the annotation
* is declared as a meta-annotation on some other annotation which is
* <em>present</em> on the element.
*
* <h3>Meta-annotation Support</h3>
* <p>Most {@code find*()} methods and some {@code get*()} methods in this class
* provide support for meta-annotations. Consult the Javadoc for each method in
* this class for details. For support for meta-annotations with
* <em>attribute overrides</em> in <em>composed annotations</em>, use
* {@link AnnotatedElementUtils} instead.
* <p>Most {@code find*()} methods and some {@code get*()} methods in this
* class provide support for finding annotations used as meta-annotations.
* Consult the Javadoc for each method in this class for details. For support
* for meta-annotations with <em>attribute overrides</em> in
* <em>composed annotations</em>, use {@link AnnotatedElementUtils} instead.
*
* <h3>Search Scope</h3>
* <p>The search algorithms used by methods in this class stop searching for
@ -122,8 +130,8 @@ public abstract class AnnotationUtils { @@ -122,8 +130,8 @@ public abstract class AnnotationUtils {
/**
* Get a single {@link Annotation} of {@code annotationType} from the supplied
* {@link AnnotatedElement}, where the {@code AnnotatedElement} is either
* directly annotated or meta-annotated with the {@code annotationType}.
* {@link AnnotatedElement}, where the annotation is either <em>present</em> or
* <em>meta-present</em> on the {@code AnnotatedElement}.
* <p>Note that this method supports only a single level of meta-annotations.
* For support for arbitrary levels of meta-annotations, use
* {@link #findAnnotation(AnnotatedElement, Class)} instead.
@ -154,8 +162,8 @@ public abstract class AnnotationUtils { @@ -154,8 +162,8 @@ public abstract class AnnotationUtils {
/**
* Get a single {@link Annotation} of {@code annotationType} from the
* supplied {@link Method}, where the method is either directly annotated
* or meta-annotated with the {@code annotationType}.
* supplied {@link Method}, where the annotation is either <em>present</em>
* or <em>meta-present</em> on the method.
* <p>Correctly handles bridge {@link Method Methods} generated by the compiler.
* <p>Note that this method supports only a single level of meta-annotations.
* For support for arbitrary levels of meta-annotations, use
@ -216,15 +224,17 @@ public abstract class AnnotationUtils { @@ -216,15 +224,17 @@ public abstract class AnnotationUtils {
}
/**
* Get the possibly repeating {@link Annotation}s of {@code annotationType}
* from the supplied {@link Method}.
* <p>Deals with both a single direct annotation and repeating annotations
* nested within a containing annotation.
* Get the <em>repeatable</em> {@link Annotation}s of {@code annotationType}
* from the supplied {@link Method}, where such annotations are either
* <em>present</em> or <em>meta-present</em> on the method.
* <p>Handles both single annotations and annotations nested within a
* <em>containing annotation</em>.
* <p>Correctly handles bridge {@link Method Methods} generated by the compiler.
* <p>Meta-annotations will be searched if the annotation is not
* <em>directly present</em> on the supplied method.
* @param method the method to look for annotations on
* @param containerAnnotationType the class of the container that holds the annotations
* <em>present</em> on the supplied method.
* @param method the method to look for annotations on; never {@code null}
* @param containerAnnotationType the type of the container that holds the
* annotations; may be {@code null} if a container is not supported
* @param annotationType the annotation type to look for
* @return the annotations found or an empty set; never {@code null}
* @since 4.0
@ -239,14 +249,16 @@ public abstract class AnnotationUtils { @@ -239,14 +249,16 @@ public abstract class AnnotationUtils {
}
/**
* Get the possibly repeating {@link Annotation}s of {@code annotationType} from the
* supplied {@link AnnotatedElement}.
* <p>Deals with both a single direct annotation and repeating annotations
* nested within a containing annotation.
* Get the <em>repeatable</em> {@link Annotation}s of {@code annotationType}
* from the supplied {@link AnnotatedElement}, where such annotations are
* either <em>present</em> or <em>meta-present</em> on the element.
* <p>Handles both single annotations and annotations nested within a
* <em>containing annotation</em>.
* <p>Meta-annotations will be searched if the annotation is not
* <em>directly present</em> on the supplied element.
* @param annotatedElement the element to look for annotations on
* @param containerAnnotationType the class of the container that holds the annotations
* <em>present</em> on the supplied element.
* @param annotatedElement the element to look for annotations on; never {@code null}
* @param containerAnnotationType the type of the container that holds the
* annotations; may be {@code null} if a container is not supported
* @param annotationType the annotation type to look for
* @return the annotations found or an empty set; never {@code null}
* @since 4.0
@ -328,7 +340,8 @@ public abstract class AnnotationUtils { @@ -328,7 +340,8 @@ public abstract class AnnotationUtils {
/**
* Find a single {@link Annotation} of {@code annotationType} on the supplied
* {@link Method}, traversing its super methods (i.e., from superclasses and
* interfaces) if no annotation can be found on the given method itself.
* interfaces) if the annotation is not <em>directly present</em> on the given
* method itself.
* <p>Correctly handles bridge {@link Method Methods} generated by the compiler.
* <p>Meta-annotations will be searched if the annotation is not
* <em>directly present</em> on the method.
@ -423,8 +436,8 @@ public abstract class AnnotationUtils { @@ -423,8 +436,8 @@ public abstract class AnnotationUtils {
/**
* Find a single {@link Annotation} of {@code annotationType} on the
* supplied {@link Class}, traversing its interfaces, annotations, and
* superclasses if the annotation is not <em>present</em> on the given class
* itself.
* superclasses if the annotation is not <em>directly present</em> on
* the given class itself.
* <p>This method explicitly handles class-level annotations which are not
* declared as {@link java.lang.annotation.Inherited inherited} <em>as well
* as meta-annotations and annotations on interfaces</em>.
@ -505,21 +518,22 @@ public abstract class AnnotationUtils { @@ -505,21 +518,22 @@ public abstract class AnnotationUtils {
}
/**
* Find the first {@link Class} in the inheritance hierarchy of the specified {@code clazz}
* (including the specified {@code clazz} itself) which declares an annotation for the
* specified {@code annotationType}, or {@code null} if not found. If the supplied
* {@code clazz} is {@code null}, {@code null} will be returned.
* <p>If the supplied {@code clazz} is an interface, only the interface itself will be checked;
* the inheritance hierarchy for interfaces will not be traversed.
* Find the first {@link Class} in the inheritance hierarchy of the
* specified {@code clazz} (including the specified {@code clazz} itself)
* on which an annotation of the specified {@code annotationType} is
* <em>directly present</em>.
* <p>If the supplied {@code clazz} is an interface, only the interface
* itself will be checked; the inheritance hierarchy for interfaces will
* not be traversed.
* <p>Meta-annotations will <em>not</em> be searched.
* <p>The standard {@link Class} API does not provide a mechanism for determining which class
* in an inheritance hierarchy actually declares an {@link Annotation}, so we need to handle
* this explicitly.
* @param annotationType the annotation type to look for, both locally and as a meta-annotation
* @param clazz the class on which to check for the annotation (may be {@code null})
* @return the first {@link Class} in the inheritance hierarchy of the specified {@code clazz}
* which declares an annotation of the specified {@code annotationType}, or {@code null}
* if not found
* <p>The standard {@link Class} API does not provide a mechanism for
* determining which class in an inheritance hierarchy actually declares
* an {@link Annotation}, so we need to handle this explicitly.
* @param annotationType the annotation type to look for
* @param clazz the class to check for the annotation on (may be {@code null})
* @return the first {@link Class} in the inheritance hierarchy that
* declares an annotation of the specified {@code annotationType}, or
* {@code null} if not found
* @see Class#isAnnotationPresent(Class)
* @see Class#getDeclaredAnnotations()
* @see #findAnnotationDeclaringClassForTypes(List, Class)
@ -537,25 +551,22 @@ public abstract class AnnotationUtils { @@ -537,25 +551,22 @@ public abstract class AnnotationUtils {
}
/**
* Find the first {@link Class} in the inheritance hierarchy of the specified
* {@code clazz} (including the specified {@code clazz} itself) which declares
* at least one of the specified {@code annotationTypes}, or {@code null} if
* none of the specified annotation types could be found.
* <p>If the supplied {@code clazz} is {@code null}, {@code null} will be
* returned.
* <p>If the supplied {@code clazz} is an interface, only the interface itself
* will be checked; the inheritance hierarchy for interfaces will not be traversed.
* Find the first {@link Class} in the inheritance hierarchy of the
* specified {@code clazz} (including the specified {@code clazz} itself)
* on which at least one of the specified {@code annotationTypes} is
* <em>directly present</em>.
* <p>If the supplied {@code clazz} is an interface, only the interface
* itself will be checked; the inheritance hierarchy for interfaces will
* not be traversed.
* <p>Meta-annotations will <em>not</em> be searched.
* <p>The standard {@link Class} API does not provide a mechanism for determining
* which class in an inheritance hierarchy actually declares one of several
* candidate {@linkplain Annotation annotations}, so we need to handle this
* explicitly.
* @param annotationTypes the list of Class objects corresponding to the
* annotation types
* @param clazz the Class object corresponding to the class on which to check
* for the annotations, or {@code null}
* @return the first {@link Class} in the inheritance hierarchy of the specified
* {@code clazz} which declares an annotation of at least one of the specified
* <p>The standard {@link Class} API does not provide a mechanism for
* determining which class in an inheritance hierarchy actually declares
* one of several candidate {@linkplain Annotation annotations}, so we
* need to handle this explicitly.
* @param annotationTypes the annotation types to look for
* @param clazz the class to check for the annotations on, or {@code null}
* @return the first {@link Class} in the inheritance hierarchy that
* declares an annotation of at least one of the specified
* {@code annotationTypes}, or {@code null} if not found
* @since 3.2.2
* @see Class#isAnnotationPresent(Class)
@ -577,18 +588,19 @@ public abstract class AnnotationUtils { @@ -577,18 +588,19 @@ public abstract class AnnotationUtils {
}
/**
* Determine whether an annotation of the specified {@code annotationType} is
* declared locally (i.e., <em>directly present</em>) on the supplied
* {@code clazz}. The supplied {@link Class} may represent any type.
* Determine whether an annotation of the specified {@code annotationType}
* is declared locally (i.e., <em>directly present</em>) on the supplied
* {@code clazz}.
* <p>The supplied {@link Class} may represent any type.
* <p>Meta-annotations will <em>not</em> be searched.
* <p>Note: This method does <strong>not</strong> determine if the annotation is
* {@linkplain java.lang.annotation.Inherited inherited}. For greater clarity
* regarding inherited annotations, consider using
* <p>Note: This method does <strong>not</strong> determine if the annotation
* is {@linkplain java.lang.annotation.Inherited inherited}. For greater
* clarity regarding inherited annotations, consider using
* {@link #isAnnotationInherited(Class, Class)} instead.
* @param annotationType the Class object corresponding to the annotation type
* @param clazz the Class object corresponding to the class on which to check for the annotation
* @param annotationType the annotation type to look for
* @param clazz the class to check for the annotation on
* @return {@code true} if an annotation of the specified {@code annotationType}
* is <em>directly present</em> on the supplied {@code clazz}
* is <em>directly present</em>
* @see java.lang.Class#getDeclaredAnnotations()
* @see java.lang.Class#getDeclaredAnnotation(Class)
* @see #isAnnotationInherited(Class, Class)
@ -596,12 +608,10 @@ public abstract class AnnotationUtils { @@ -596,12 +608,10 @@ public abstract class AnnotationUtils {
public static boolean isAnnotationDeclaredLocally(Class<? extends Annotation> annotationType, Class<?> clazz) {
Assert.notNull(annotationType, "Annotation type must not be null");
Assert.notNull(clazz, "Class must not be null");
boolean declaredLocally = false;
try {
for (Annotation ann : clazz.getDeclaredAnnotations()) {
if (ann.annotationType().equals(annotationType)) {
declaredLocally = true;
break;
return true;
}
}
}
@ -609,22 +619,25 @@ public abstract class AnnotationUtils { @@ -609,22 +619,25 @@ public abstract class AnnotationUtils {
// Assuming nested Class values not resolvable within annotation attributes...
logIntrospectionFailure(clazz, ex);
}
return declaredLocally;
return false;
}
/**
* Determine whether an annotation of the specified {@code annotationType} is <em>present</em>
* on the supplied {@code clazz} and is {@linkplain java.lang.annotation.Inherited inherited}
* (i.e., not declared locally for the class).
* Determine whether an annotation of the specified {@code annotationType}
* is <em>present</em> on the supplied {@code clazz} and is
* {@linkplain java.lang.annotation.Inherited inherited} (i.e., not
* <em>directly present</em>).
* <p>Meta-annotations will <em>not</em> be searched.
* <p>If the supplied {@code clazz} is an interface, only the interface itself will be checked.
* In accordance with standard meta-annotation semantics, the inheritance hierarchy for interfaces
* will not be traversed. See the {@linkplain java.lang.annotation.Inherited Javadoc} for the
* {@code @Inherited} meta-annotation for further details regarding annotation inheritance.
* @param annotationType the Class object corresponding to the annotation type
* @param clazz the Class object corresponding to the class on which to check for the annotation
* @return {@code true} if an annotation of the specified {@code annotationType} is present
* on the supplied {@code clazz} and is <em>inherited</em>
* <p>If the supplied {@code clazz} is an interface, only the interface
* itself will be checked. In accordance with standard meta-annotation
* semantics in Java, the inheritance hierarchy for interfaces will not
* be traversed. See the {@linkplain java.lang.annotation.Inherited Javadoc}
* for the {@code @Inherited} meta-annotation for further details regarding
* annotation inheritance.
* @param annotationType the annotation type to look for
* @param clazz the class to check for the annotation on
* @return {@code true} if an annotation of the specified {@code annotationType}
* is <em>present</em> and <em>inherited</em>
* @see Class#isAnnotationPresent(Class)
* @see #isAnnotationDeclaredLocally(Class, Class)
*/

Loading…
Cancel
Save