diff --git a/spring-core/src/main/java/org/springframework/core/annotation/AnnotatedElementUtils.java b/spring-core/src/main/java/org/springframework/core/annotation/AnnotatedElementUtils.java index dd10bd53489..c52937b7a1e 100644 --- a/spring-core/src/main/java/org/springframework/core/annotation/AnnotatedElementUtils.java +++ b/spring-core/src/main/java/org/springframework/core/annotation/AnnotatedElementUtils.java @@ -314,39 +314,21 @@ public class AnnotatedElementUtils { } /** - * Get the first annotation of the specified {@code annotationType} within - * the annotation hierarchy above the supplied {@code element}, - * merge that annotation's attributes with matching attributes from - * annotations in lower levels of the annotation hierarchy, and synthesize - * the result back into an annotation of the specified {@code annotationType}. - *
{@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)
+ * @deprecated As of Spring Framework 4.2, use {@link #getMergedAnnotationAttributes(AnnotatedElement, String)} instead.
*/
- public static A getMergedAnnotation(AnnotatedElement element, Class annotationType) {
- Assert.notNull(annotationType, "annotationType must not be null");
+ @Deprecated
+ public static AnnotationAttributes getAnnotationAttributes(AnnotatedElement element, String annotationName) {
+ return getMergedAnnotationAttributes(element, annotationName);
+ }
- // Shortcut: directly present on the element, with no merging needed?
- if (!(element instanceof Class)) {
- // Do not use this shortcut against a Class: Inherited annotations
- // would get preferred over locally declared composed annotations.
- A annotation = element.getAnnotation(annotationType);
- if (annotation != null) {
- return AnnotationUtils.synthesizeAnnotation(annotation, element);
- }
- }
+ /**
+ * @deprecated As of Spring Framework 4.2, use {@link #getMergedAnnotationAttributes(AnnotatedElement, String, boolean, boolean)} instead.
+ */
+ @Deprecated
+ public static AnnotationAttributes getAnnotationAttributes(AnnotatedElement element, String annotationName,
+ boolean classValuesAsString, boolean nestedAnnotationsAsMap) {
- // Exhaustive retrieval of merged annotation attributes...
- AnnotationAttributes attributes = getMergedAnnotationAttributes(element, annotationType);
- return AnnotationUtils.synthesizeAnnotation(attributes, annotationType, element);
+ return getMergedAnnotationAttributes(element, annotationName, classValuesAsString, nestedAnnotationsAsMap);
}
/**
@@ -433,6 +415,102 @@ public class AnnotatedElementUtils {
return attributes;
}
+ /**
+ * Get the first annotation of the specified {@code annotationType} within
+ * the annotation hierarchy above the supplied {@code element},
+ * merge that annotation's attributes with matching attributes from
+ * annotations in lower levels of the annotation hierarchy, and synthesize
+ * the result back into an annotation of the specified {@code annotationType}.
+ * {@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)
+ */
+ public static A getMergedAnnotation(AnnotatedElement element, Class annotationType) {
+ Assert.notNull(annotationType, "annotationType must not be null");
+
+ // Shortcut: directly present on the element, with no merging needed?
+ if (!(element instanceof Class)) {
+ // Do not use this shortcut against a Class: Inherited annotations
+ // would get preferred over locally declared composed annotations.
+ A annotation = element.getAnnotation(annotationType);
+ if (annotation != null) {
+ return AnnotationUtils.synthesizeAnnotation(annotation, element);
+ }
+ }
+
+ // Exhaustive retrieval of merged annotation attributes...
+ AnnotationAttributes attributes = getMergedAnnotationAttributes(element, annotationType);
+ return AnnotationUtils.synthesizeAnnotation(attributes, annotationType, element);
+ }
+
+ /**
+ * Get the annotation attributes of all annotations of the specified
+ * {@code annotationName} in the annotation hierarchy above the supplied
+ * {@link AnnotatedElement} and store the results in a {@link MultiValueMap}.
+ * Note: in contrast to {@link #getMergedAnnotationAttributes(AnnotatedElement, String)},
+ * this method does not support attribute overrides.
+ * This method follows get semantics as described in the
+ * {@linkplain AnnotatedElementUtils class-level javadoc}.
+ * @param element the annotated element
+ * @param annotationName the fully qualified class name of the annotation type to find
+ * @return a {@link MultiValueMap} keyed by attribute name, containing the annotation
+ * attributes from all annotations found, or {@code null} if not found
+ * @see #getAllAnnotationAttributes(AnnotatedElement, String, boolean, boolean)
+ */
+ public static MultiValueMap Note: in contrast to {@link #getMergedAnnotationAttributes(AnnotatedElement, String)},
+ * this method does not support attribute overrides.
+ * This method follows get semantics as described in the
+ * {@linkplain AnnotatedElementUtils class-level javadoc}.
+ * @param element the annotated element
+ * @param annotationName the fully qualified class name of the annotation type to find
+ * @param classValuesAsString whether to convert Class references into Strings or to
+ * preserve them as Class references
+ * @param nestedAnnotationsAsMap whether to convert nested Annotation instances into
+ * {@code AnnotationAttributes} maps or to preserve them as Annotation instances
+ * @return a {@link MultiValueMap} keyed by attribute name, containing the annotation
+ * attributes from all annotations found, or {@code null} if not found
+ */
+ public static MultiValueMap Attributes from lower levels in the annotation hierarchy override
+ * attributes of the same name from higher levels, and
+ * {@link AliasFor @AliasFor} semantics are fully supported, both
+ * within a single annotation and within the annotation hierarchy.
+ * In contrast to {@link #getAllAnnotationAttributes}, the search
+ * algorithm used by this method will stop searching the annotation
+ * hierarchy once the first annotation of the specified
+ * {@code annotationType} has been found. As a consequence, additional
+ * annotations of the specified {@code annotationType} will be ignored.
+ * This method follows find semantics as described in the
+ * {@linkplain AnnotatedElementUtils class-level javadoc}.
+ * @param element the annotated element
+ * @param annotationType the annotation type to find
+ * @param classValuesAsString whether to convert Class references into
+ * Strings or to preserve them as Class references
+ * @param nestedAnnotationsAsMap whether to convert nested Annotation
+ * instances into {@code AnnotationAttributes} maps or to preserve them
+ * as Annotation instances
+ * @return the merged {@code AnnotationAttributes}, or {@code null} if
+ * not found
+ * @since 4.2
+ * @see #findMergedAnnotation(AnnotatedElement, Class)
+ * @see #getMergedAnnotationAttributes(AnnotatedElement, String, boolean, boolean)
+ */
+ public static AnnotationAttributes findMergedAnnotationAttributes(AnnotatedElement element,
+ Class extends Annotation> annotationType, boolean classValuesAsString, boolean nestedAnnotationsAsMap) {
+
+ AnnotationAttributes attributes = searchWithFindSemantics(element, annotationType, annotationType.getName(),
+ new MergedAnnotationAttributesProcessor(annotationType, null, classValuesAsString, nestedAnnotationsAsMap));
+ AnnotationUtils.postProcessAnnotationAttributes(element, attributes, classValuesAsString, nestedAnnotationsAsMap);
+ return attributes;
+ }
+
+ /**
+ * Find the first annotation of the specified {@code annotationName} within
+ * the annotation hierarchy above the supplied {@code element} and
+ * merge that annotation's attributes with matching attributes from
+ * annotations in lower levels of the annotation hierarchy.
+ * Attributes from lower levels in the annotation hierarchy override
+ * attributes of the same name from higher levels, and
+ * {@link AliasFor @AliasFor} semantics are fully supported, both
+ * within a single annotation and within the annotation hierarchy.
+ * In contrast to {@link #getAllAnnotationAttributes}, the search
+ * algorithm used by this method will stop searching the annotation
+ * hierarchy once the first annotation of the specified
+ * {@code annotationName} has been found. As a consequence, additional
+ * annotations of the specified {@code annotationName} will be ignored.
+ * This method follows find semantics as described in the
+ * {@linkplain AnnotatedElementUtils class-level javadoc}.
+ * @param element the annotated element
+ * @param annotationName the fully qualified class name of the annotation type to find
+ * @param classValuesAsString whether to convert Class references into Strings or to
+ * preserve them as Class references
+ * @param nestedAnnotationsAsMap whether to convert nested Annotation instances into
+ * {@code AnnotationAttributes} maps or to preserve them as Annotation instances
+ * @return the merged {@code AnnotationAttributes}, or {@code null} if not found
+ * @since 4.2
+ * @see #findMergedAnnotation(AnnotatedElement, Class)
+ * @see #getMergedAnnotationAttributes(AnnotatedElement, String, boolean, boolean)
+ */
+ public static AnnotationAttributes findMergedAnnotationAttributes(AnnotatedElement element,
+ String annotationName, boolean classValuesAsString, boolean nestedAnnotationsAsMap) {
+
+ AnnotationAttributes attributes = searchWithFindSemantics(element, null, annotationName,
+ new MergedAnnotationAttributesProcessor(null, annotationName, classValuesAsString, nestedAnnotationsAsMap));
+ AnnotationUtils.postProcessAnnotationAttributes(element, attributes, classValuesAsString, nestedAnnotationsAsMap);
+ return attributes;
+ }
+
/**
* Find the first annotation of the specified {@code annotationType} within
* the annotation hierarchy above the supplied {@code element},
@@ -630,20 +782,14 @@ public class AnnotatedElementUtils {
Assert.notNull(annotationType, "annotationType must not be null");
if (containerType == null) {
- containerType = AnnotationUtils.resolveContainerAnnotationType(annotationType);
- if (containerType == null) {
- throw new IllegalArgumentException(
- "annotationType must be a repeatable annotation: failed to resolve container type for "
- + annotationType.getName());
- }
+ containerType = resolveContainerType(annotationType);
}
else {
validateRepeatableContainerType(annotationType, containerType);
}
- MergedAnnotationAttributesProcessor processor = new MergedAnnotationAttributesProcessor(annotationType, null,
- false, false, true);
-
+ MergedAnnotationAttributesProcessor processor =
+ new MergedAnnotationAttributesProcessor(annotationType, null, false, false, true);
searchWithFindSemantics(element, annotationType, annotationType.getName(), containerType, processor);
Set annotations = new LinkedHashSet();
@@ -654,158 +800,6 @@ public class AnnotatedElementUtils {
return annotations;
}
- /**
- * Find the first annotation of the specified {@code annotationType} within
- * the annotation hierarchy above the supplied {@code element} and
- * merge that annotation's attributes with matching attributes from
- * annotations in lower levels of the annotation hierarchy.
- * Attributes from lower levels in the annotation hierarchy override
- * attributes of the same name from higher levels, and
- * {@link AliasFor @AliasFor} semantics are fully supported, both
- * within a single annotation and within the annotation hierarchy.
- * In contrast to {@link #getAllAnnotationAttributes}, the search
- * algorithm used by this method will stop searching the annotation
- * hierarchy once the first annotation of the specified
- * {@code annotationType} has been found. As a consequence, additional
- * annotations of the specified {@code annotationType} will be ignored.
- * This method follows find semantics as described in the
- * {@linkplain AnnotatedElementUtils class-level javadoc}.
- * @param element the annotated element
- * @param annotationType the annotation type to find
- * @param classValuesAsString whether to convert Class references into
- * Strings or to preserve them as Class references
- * @param nestedAnnotationsAsMap whether to convert nested Annotation
- * instances into {@code AnnotationAttributes} maps or to preserve them
- * as Annotation instances
- * @return the merged {@code AnnotationAttributes}, or {@code null} if
- * not found
- * @since 4.2
- * @see #findMergedAnnotation(AnnotatedElement, Class)
- * @see #getMergedAnnotationAttributes(AnnotatedElement, String, boolean, boolean)
- */
- public static AnnotationAttributes findMergedAnnotationAttributes(AnnotatedElement element,
- Class extends Annotation> annotationType, boolean classValuesAsString, boolean nestedAnnotationsAsMap) {
-
- AnnotationAttributes attributes = searchWithFindSemantics(element, annotationType, annotationType.getName(),
- new MergedAnnotationAttributesProcessor(annotationType, null, classValuesAsString, nestedAnnotationsAsMap));
- AnnotationUtils.postProcessAnnotationAttributes(element, attributes, classValuesAsString, nestedAnnotationsAsMap);
- return attributes;
- }
-
- /**
- * Find the first annotation of the specified {@code annotationName} within
- * the annotation hierarchy above the supplied {@code element} and
- * merge that annotation's attributes with matching attributes from
- * annotations in lower levels of the annotation hierarchy.
- * Attributes from lower levels in the annotation hierarchy override
- * attributes of the same name from higher levels, and
- * {@link AliasFor @AliasFor} semantics are fully supported, both
- * within a single annotation and within the annotation hierarchy.
- * In contrast to {@link #getAllAnnotationAttributes}, the search
- * algorithm used by this method will stop searching the annotation
- * hierarchy once the first annotation of the specified
- * {@code annotationName} has been found. As a consequence, additional
- * annotations of the specified {@code annotationName} will be ignored.
- * This method follows find semantics as described in the
- * {@linkplain AnnotatedElementUtils class-level javadoc}.
- * @param element the annotated element
- * @param annotationName the fully qualified class name of the annotation type to find
- * @param classValuesAsString whether to convert Class references into Strings or to
- * preserve them as Class references
- * @param nestedAnnotationsAsMap whether to convert nested Annotation instances into
- * {@code AnnotationAttributes} maps or to preserve them as Annotation instances
- * @return the merged {@code AnnotationAttributes}, or {@code null} if not found
- * @since 4.2
- * @see #findMergedAnnotation(AnnotatedElement, Class)
- * @see #getMergedAnnotationAttributes(AnnotatedElement, String, boolean, boolean)
- */
- public static AnnotationAttributes findMergedAnnotationAttributes(AnnotatedElement element,
- String annotationName, boolean classValuesAsString, boolean nestedAnnotationsAsMap) {
-
- AnnotationAttributes attributes = searchWithFindSemantics(element, null, annotationName,
- new MergedAnnotationAttributesProcessor(null, annotationName, classValuesAsString, nestedAnnotationsAsMap));
- AnnotationUtils.postProcessAnnotationAttributes(element, attributes, classValuesAsString, nestedAnnotationsAsMap);
- return attributes;
- }
-
- /**
- * @deprecated As of Spring Framework 4.2, use {@link #getMergedAnnotationAttributes(AnnotatedElement, String)} instead.
- */
- @Deprecated
- public static AnnotationAttributes getAnnotationAttributes(AnnotatedElement element, String annotationName) {
- return getMergedAnnotationAttributes(element, annotationName);
- }
-
- /**
- * @deprecated As of Spring Framework 4.2, use {@link #getMergedAnnotationAttributes(AnnotatedElement, String, boolean, boolean)} instead.
- */
- @Deprecated
- public static AnnotationAttributes getAnnotationAttributes(AnnotatedElement element, String annotationName,
- boolean classValuesAsString, boolean nestedAnnotationsAsMap) {
-
- return getMergedAnnotationAttributes(element, annotationName, classValuesAsString, nestedAnnotationsAsMap);
- }
-
- /**
- * Get the annotation attributes of all annotations of the specified
- * {@code annotationName} in the annotation hierarchy above the supplied
- * {@link AnnotatedElement} and store the results in a {@link MultiValueMap}.
- * Note: in contrast to {@link #getMergedAnnotationAttributes(AnnotatedElement, String)},
- * this method does not support attribute overrides.
- * This method follows get semantics as described in the
- * {@linkplain AnnotatedElementUtils class-level javadoc}.
- * @param element the annotated element
- * @param annotationName the fully qualified class name of the annotation type to find
- * @return a {@link MultiValueMap} keyed by attribute name, containing the annotation
- * attributes from all annotations found, or {@code null} if not found
- * @see #getAllAnnotationAttributes(AnnotatedElement, String, boolean, boolean)
- */
- public static MultiValueMap Note: in contrast to {@link #getMergedAnnotationAttributes(AnnotatedElement, String)},
- * this method does not support attribute overrides.
- * This method follows get semantics as described in the
- * {@linkplain AnnotatedElementUtils class-level javadoc}.
- * @param element the annotated element
- * @param annotationName the fully qualified class name of the annotation type to find
- * @param classValuesAsString whether to convert Class references into Strings or to
- * preserve them as Class references
- * @param nestedAnnotationsAsMap whether to convert nested Annotation instances into
- * {@code AnnotationAttributes} maps or to preserve them as Annotation instances
- * @return a {@link MultiValueMap} keyed by attribute name, containing the annotation
- * attributes from all annotations found, or {@code null} if not found
- */
- public static MultiValueMap Delegates to {@link AnnotationUtils#resolveContainerAnnotationType(Class)}.
+ * @param annotationType the annotation type to resolve the container for
+ * @return the container type; never {@code null}
+ * @throws IllegalArgumentException if the container type cannot be resolved
+ * @since 4.3
+ */
+ private static Class extends Annotation> resolveContainerType(Class extends Annotation> annotationType) {
+ Class extends Annotation> containerType = AnnotationUtils.resolveContainerAnnotationType(annotationType);
+ if (containerType == null) {
+ throw new IllegalArgumentException(
+ "annotationType must be a repeatable annotation: failed to resolve container type for "
+ + annotationType.getName());
+ }
+ return containerType;
+ }
+
/**
* Validate that the supplied {@code containerType} is a proper container
* annotation for the supplied repeatable {@code annotationType} (i.e.,