{@link AliasFor @AliasFor} semantics are fully supported, both * within a single annotation and within the annotation hierarchy. - *
This method delegates to {@link #getMergedAnnotationAttributes(AnnotatedElement, Class)}
- * and {@link AnnotationUtils#synthesizeAnnotation(Map, Class, AnnotatedElement)}.
* @param element the annotated element
* @param annotationType the annotation type to find
* @return the merged, synthesized {@code Annotation}, or {@code null} if not found
* @since 4.2
- * @see #getMergedAnnotationAttributes(AnnotatedElement, Class)
* @see #findMergedAnnotation(AnnotatedElement, Class)
- * @see AnnotationUtils#synthesizeAnnotation(Map, Class, AnnotatedElement)
*/
@Nullable
- public static A getMergedAnnotation(AnnotatedElement element,
- Class annotationType) {
-
- if (AnnotationsScanner.hasPlainJavaAnnotationsOnly(element)) {
- return null;
- }
- A annotation = AnnotationsScanner.getDeclaredAnnotation(element, annotationType);
- if (annotation != null) {
- return AnnotationUtils.synthesizeAnnotation(annotation, element);
- }
+ public static A getMergedAnnotation(AnnotatedElement element, Class annotationType) {
+ // Shortcut: directly present on the element, with no merging needed?
+ if (AnnotationFilter.PLAIN.matches(annotationType)) {
+ return element.getDeclaredAnnotation(annotationType);
+ }
+ // Shortcut: no searchable annotations to be found on plain Java classes and core Spring types...
if (AnnotationsScanner.hasPlainJavaAnnotationsOnly(element)) {
return null;
}
+ // Exhaustive retrieval of merged annotations...
return getAnnotations(element)
.get(annotationType, null, MergedAnnotationSelectors.firstDirectlyDeclared())
.synthesize(MergedAnnotation::isPresent).orElse(null);
@@ -515,9 +503,8 @@ public abstract class AnnotatedElementUtils {
* attributes from all annotations found, or {@code null} if not found
*/
@Nullable
- public static MultiValueMap 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 get lookup on the given class level only
- * ({@link #getAnnotation(Method, Class)}) and a find lookup in the entire
- * inheritance hierarchy of the given method ({@link #findAnnotation(Method, Class)}).
+ * on this class (e.g., {@link #findAnnotation(Method, Class)} and
+ * {@link #getAnnotation(Method, Class)}) instead of the plain annotation lookup
+ * methods in the JDK. You can still explicitly choose between a get
+ * lookup on the given class level only ({@link #getAnnotation(Method, Class)})
+ * and a find lookup in the entire inheritance hierarchy of the given
+ * method ({@link #findAnnotation(Method, Class)}).
*
* The supplied {@link Class} may represent any type.
* Meta-annotations will not be searched.
* Note: This method does not determine if the annotation
- * is {@linkplain java.lang.annotation.Inherited inherited}. For greater
- * clarity regarding inherited annotations, consider using
- * {@link #isAnnotationInherited(Class, Class)} instead.
+ * is {@linkplain java.lang.annotation.Inherited inherited}.
* @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 directly present
* @see java.lang.Class#getDeclaredAnnotations()
* @see java.lang.Class#getDeclaredAnnotation(Class)
- * @see #isAnnotationInherited(Class, Class)
*/
public static boolean isAnnotationDeclaredLocally(Class extends Annotation> annotationType, Class> clazz) {
return MergedAnnotations.from(clazz).get(annotationType).isDirectlyPresent();
@@ -638,7 +682,9 @@ public abstract class AnnotationUtils {
* is present and inherited
* @see Class#isAnnotationPresent(Class)
* @see #isAnnotationDeclaredLocally(Class, Class)
+ * @deprecated as of 5.2 since it is superseded by the {@link MergedAnnotations} API
*/
+ @Deprecated
public static boolean isAnnotationInherited(Class extends Annotation> annotationType, Class> clazz) {
return MergedAnnotations.from(clazz, SearchStrategy.INHERITED_ANNOTATIONS)
.stream(annotationType)
@@ -654,11 +700,27 @@ public abstract class AnnotationUtils {
* @param metaAnnotationType the type of meta-annotation to search for
* @return {@code true} if such an annotation is meta-present
* @since 4.2.1
+ * @deprecated as of 5.2 since it is superseded by the {@link MergedAnnotations} API
*/
+ @Deprecated
public static boolean isAnnotationMetaPresent(Class extends Annotation> annotationType,
@Nullable Class extends Annotation> metaAnnotationType) {
- return MergedAnnotations.from(annotationType, SearchStrategy.EXHAUSTIVE).isPresent(annotationType);
+ if (metaAnnotationType == null) {
+ return false;
+ }
+ // Shortcut: directly present on the element, with no merging needed?
+ if (AnnotationFilter.PLAIN.matches(annotationType) ||
+ AnnotationFilter.PLAIN.matches(metaAnnotationType)) {
+ return annotationType.isAnnotationPresent(metaAnnotationType);
+ }
+ // Shortcut: no searchable annotations to be found on plain Java classes and core Spring types...
+ if (AnnotationsScanner.hasPlainJavaAnnotationsOnly(annotationType)) {
+ return false;
+ }
+ // Exhaustive retrieval of merged annotations...
+ return (MergedAnnotations.from(
+ annotationType, SearchStrategy.INHERITED_ANNOTATIONS).isPresent(metaAnnotationType));
}
/**
@@ -731,8 +793,8 @@ public abstract class AnnotationUtils {
* corresponding attribute values as values (never {@code null})
* @see #getAnnotationAttributes(Annotation, boolean, boolean)
*/
- public static Map This method simply delegates to
+ * {@link #synthesizeAnnotation(Map, Class, AnnotatedElement)},
+ * supplying an empty map for the source attribute values and {@code null}
+ * for the {@link AnnotatedElement}.
+ * @param annotationType the type of annotation to synthesize
+ * @return the synthesized annotation
+ * @throws IllegalArgumentException if a required attribute is missing
+ * @throws AnnotationConfigurationException if invalid configuration of
+ * {@code @AliasFor} is detected
+ * @since 4.2
+ * @see #synthesizeAnnotation(Map, Class, AnnotatedElement)
+ * @see #synthesizeAnnotation(Annotation, AnnotatedElement)
+ */
+ public static A synthesizeAnnotation(Class annotationType) {
+ return synthesizeAnnotation(Collections.emptyMap(), annotationType, null);
}
/**
@@ -1177,38 +1237,17 @@ public abstract class AnnotationUtils {
* @see #getAnnotationAttributes(AnnotatedElement, Annotation)
* @see #getAnnotationAttributes(AnnotatedElement, Annotation, boolean, boolean)
*/
- public static A synthesizeAnnotation(
- Map This method simply delegates to
- * {@link #synthesizeAnnotation(Map, Class, AnnotatedElement)},
- * supplying an empty map for the source attribute values and {@code null}
- * for the {@link AnnotatedElement}.
- * @param annotationType the type of annotation to synthesize
- * @return the synthesized annotation
- * @throws IllegalArgumentException if a required attribute is missing
- * @throws AnnotationConfigurationException if invalid configuration of
- * {@code @AliasFor} is detected
- * @since 4.2
- * @see #synthesizeAnnotation(Map, Class, AnnotatedElement)
- * @see #synthesizeAnnotation(Annotation, AnnotatedElement)
- */
- public static A synthesizeAnnotation(Class annotationType) {
- return synthesizeAnnotation(Collections.emptyMap(), annotationType, null);
- }
-
/**
* Synthesize an array of annotations from the supplied array
* of {@code annotations} by creating a new array of the same size and
@@ -1226,9 +1265,7 @@ public abstract class AnnotationUtils {
* @see #synthesizeAnnotation(Annotation, AnnotatedElement)
* @see #synthesizeAnnotation(Map, Class, AnnotatedElement)
*/
- static Annotation[] synthesizeAnnotationArray(Annotation[] annotations,
- @Nullable Object annotatedElement) {
-
+ static Annotation[] synthesizeAnnotationArray(Annotation[] annotations, AnnotatedElement annotatedElement) {
if (AnnotationsScanner.hasPlainJavaAnnotationsOnly(annotatedElement)) {
return annotations;
}
@@ -1240,16 +1277,6 @@ public abstract class AnnotationUtils {
return synthesized;
}
- private static A synthesizeAnnotation(A annotation,
- @Nullable Object annotatedElement) {
- if (annotation instanceof SynthesizedAnnotation ||
- AnnotationsScanner.hasPlainJavaAnnotationsOnly(annotatedElement) ||
- AnnotationFilter.PLAIN.matches(annotation)) {
- return annotation;
- }
- return MergedAnnotation.from(annotatedElement, annotation).synthesize();
- }
-
/**
* Clear the internal annotation metadata cache.
* @since 4.3.15
@@ -1259,11 +1286,6 @@ public abstract class AnnotationUtils {
AnnotationsScanner.clearCache();
}
- private static boolean isSingleLevelPresent(
- MergedAnnotation mergedAnnotation) {
- int depth = mergedAnnotation.getDepth();
- return depth == 0 || depth == 1;
- }
/**
* Internal holder used to wrap default values.
@@ -1280,7 +1302,6 @@ public abstract class AnnotationUtils {
public String toString() {
return "*" + this.defaultValue;
}
-
}
}
diff --git a/spring-core/src/main/java/org/springframework/core/annotation/MergedAnnotation.java b/spring-core/src/main/java/org/springframework/core/annotation/MergedAnnotation.java
index 881f904f77..11ec3360ff 100644
--- a/spring-core/src/main/java/org/springframework/core/annotation/MergedAnnotation.java
+++ b/spring-core/src/main/java/org/springframework/core/annotation/MergedAnnotation.java
@@ -51,6 +51,7 @@ import org.springframework.lang.Nullable;
* synthesized} back into an actual {@link java.lang.annotation.Annotation}.
*
* @author Phillip Webb
+ * @author Juergen Hoeller
* @since 5.2
* @param the annotation type
* @see MergedAnnotations
@@ -65,10 +66,10 @@ public interface MergedAnnotation {
/**
- * Return the class name of the actual annotation type.
+ * Return the {@code Class} reference for the actual annotation type.
* @return the annotation type
*/
- String getType();
+ Class getType();
/**
* Return if the annotation is present on the source. Considers
@@ -323,8 +324,7 @@ public interface MergedAnnotation {
* @return the value as a enum
* @throws NoSuchElementException if there is no matching attribute
*/
- Terminology
* The terms directly present, indirectly present, and
@@ -111,14 +110,13 @@ public abstract class AnnotationUtils {
*/
public static final String VALUE = MergedAnnotation.VALUE;
-
- static final AnnotationFilter JAVA_LANG_ANNOTATION_FILTER =
+ private static final AnnotationFilter JAVA_LANG_ANNOTATION_FILTER =
AnnotationFilter.packages("java.lang.annotation");
-
private static Map
- *
*
* @author Phillip Webb
+ * @author Juergen Hoeller
* @since 5.2
* @param the annotation type
* @see TypeMappedAnnotations
@@ -91,17 +92,16 @@ final class TypeMappedAnnotation extends AbstractMergedAnn
private String string;
- private TypeMappedAnnotation(AnnotationTypeMapping mapping,
- @Nullable Object source, @Nullable Object rootAttributes,
- BiFunction
+ * Return Type Extracted Type
* Return Type Extracted Type
* Class Class or String
* Class[] Class[] or String[] Annotation Annotation, Map or Object compatible with the value
@@ -60,6 +60,7 @@ import org.springframework.util.ReflectionUtils;
*