annotationType) {
AnnotationAttributes attributes = getMergedAnnotationAttributes(element, annotationType);
- return ((attributes != null) ? AnnotationUtils.synthesizeAnnotation(attributes, annotationType, element) : null);
+ return (attributes != null ? AnnotationUtils.synthesizeAnnotation(attributes, annotationType, element) : null);
}
/**
@@ -244,8 +307,8 @@ public class AnnotatedElementUtils {
* {@link AliasFor @AliasFor} semantics are fully supported, both
* within a single annotation and within the annotation hierarchy.
*
This method delegates to {@link #getMergedAnnotationAttributes(AnnotatedElement, String)}.
- * @param element the annotated element; never {@code null}
- * @param annotationType the annotation type to find; never {@code null}
+ * @param element the annotated element
+ * @param annotationType the annotation type to find
* @return the merged {@code AnnotationAttributes}, or {@code null} if not found
* @since 4.2
* @see #getMergedAnnotationAttributes(AnnotatedElement, String, boolean, boolean)
@@ -253,17 +316,14 @@ public class AnnotatedElementUtils {
* @see #getMergedAnnotation(AnnotatedElement, Class)
* @see #findMergedAnnotation(AnnotatedElement, Class)
*/
- public static AnnotationAttributes getMergedAnnotationAttributes(AnnotatedElement element, Class extends Annotation> annotationType) {
- Assert.notNull(annotationType, "annotationType must not be null");
- return getMergedAnnotationAttributes(element, annotationType.getName());
- }
+ public static AnnotationAttributes getMergedAnnotationAttributes(
+ AnnotatedElement element, Class extends Annotation> annotationType) {
- /**
- * @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);
+ Assert.notNull(annotationType, "annotationType must not be null");
+ AnnotationAttributes attributes = searchWithGetSemantics(element, annotationType, null,
+ new MergedAnnotationAttributesProcessor(annotationType, null, false, false));
+ AnnotationUtils.postProcessAnnotationAttributes(element, attributes, false, false);
+ return attributes;
}
/**
@@ -275,11 +335,9 @@ public class AnnotatedElementUtils {
* within a single annotation and within the annotation hierarchy.
*
This method delegates to {@link #getMergedAnnotationAttributes(AnnotatedElement, String, boolean, boolean)},
* supplying {@code false} for {@code classValuesAsString} and {@code nestedAnnotationsAsMap}.
- * @param element the annotated element; never {@code null}
- * @param annotationName the fully qualified class name of the annotation
- * type to find; never {@code null} or empty
- * @return the merged {@code AnnotationAttributes}, or {@code null} if
- * not found
+ * @param element the annotated element
+ * @param annotationName the fully qualified class name of the annotation type to find
+ * @return the merged {@code AnnotationAttributes}, or {@code null} if not found
* @since 4.2
* @see #getMergedAnnotationAttributes(AnnotatedElement, String, boolean, boolean)
* @see #findMergedAnnotationAttributes(AnnotatedElement, String, boolean, boolean)
@@ -290,55 +348,37 @@ public class AnnotatedElementUtils {
return getMergedAnnotationAttributes(element, annotationName, false, false);
}
- /**
- * @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 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.
+ *
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 get semantics as described in the
- * {@linkplain AnnotatedElementUtils class-level Javadoc}.
- * @param element the annotated element; never {@code null}
- * @param annotationName the fully qualified class name of the annotation
- * type to find; never {@code null} or empty
- * @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
+ * {@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 #findMergedAnnotationAttributes(AnnotatedElement, String, boolean, boolean)
* @see #getAllAnnotationAttributes(AnnotatedElement, String, boolean, boolean)
*/
- public static AnnotationAttributes getMergedAnnotationAttributes(AnnotatedElement element, String annotationName,
- boolean classValuesAsString, boolean nestedAnnotationsAsMap) {
+ public static AnnotationAttributes getMergedAnnotationAttributes(AnnotatedElement element,
+ String annotationName, boolean classValuesAsString, boolean nestedAnnotationsAsMap) {
- if (element.getAnnotations().length == 0) {
- return null;
- }
- AnnotationAttributes attributes = searchWithGetSemantics(element, annotationName,
- new MergedAnnotationAttributesProcessor(annotationName, classValuesAsString, nestedAnnotationsAsMap));
+ AnnotationAttributes attributes = searchWithGetSemantics(element, null, annotationName,
+ new MergedAnnotationAttributesProcessor(null, annotationName, classValuesAsString, nestedAnnotationsAsMap));
AnnotationUtils.postProcessAnnotationAttributes(element, attributes, classValuesAsString, nestedAnnotationsAsMap);
return attributes;
}
@@ -352,8 +392,8 @@ public class AnnotatedElementUtils {
*
{@link AliasFor @AliasFor} semantics are fully supported, both
* within a single annotation and within the annotation hierarchy.
*
This method delegates to {@link #findMergedAnnotation(AnnotatedElement, String)}.
- * @param element the annotated element; never {@code null}
- * @param annotationType the annotation type to find; never {@code null}
+ * @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 #findMergedAnnotation(AnnotatedElement, String)
@@ -376,9 +416,8 @@ public class AnnotatedElementUtils {
*
This method delegates to {@link #findMergedAnnotationAttributes(AnnotatedElement, String, boolean, boolean)}
* (supplying {@code false} for {@code classValuesAsString} and {@code nestedAnnotationsAsMap})
* and {@link AnnotationUtils#synthesizeAnnotation(Map, Class, AnnotatedElement)}.
- * @param element the annotated element; never {@code null}
- * @param annotationName the fully qualified class name of the annotation
- * type to find; never {@code null} or empty
+ * @param element the annotated element
+ * @param annotationName the fully qualified class name of the annotation type to find
* @return the merged, synthesized {@code Annotation}, or {@code null} if not found
* @since 4.2
* @see #findMergedAnnotation(AnnotatedElement, Class)
@@ -407,10 +446,9 @@ public class AnnotatedElementUtils {
* {@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; never {@code null}
- * @param annotationName the fully qualified class name of the annotation
- * type to find; never {@code null} or empty
+ * {@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
@@ -421,31 +459,84 @@ public class AnnotatedElementUtils {
* @since 4.2
* @see #findMergedAnnotation(AnnotatedElement, Class)
* @see #getMergedAnnotationAttributes(AnnotatedElement, String, boolean, boolean)
+ * @deprecated as of 4.2.3; use {@link #findMergedAnnotation(AnnotatedElement, Class)} instead
*/
- public static AnnotationAttributes findMergedAnnotationAttributes(AnnotatedElement element, String annotationName,
- boolean classValuesAsString, boolean nestedAnnotationsAsMap) {
+ @Deprecated
+ public static AnnotationAttributes findMergedAnnotationAttributes(AnnotatedElement element,
+ Class extends Annotation> annotationType, boolean classValuesAsString, boolean nestedAnnotationsAsMap) {
- AnnotationAttributes attributes = searchWithFindSemantics(element, annotationName,
- new MergedAnnotationAttributesProcessor(annotationName, classValuesAsString, nestedAnnotationsAsMap));
+ AnnotationAttributes attributes = searchWithFindSemantics(element, annotationType, null,
+ new MergedAnnotationAttributesProcessor(annotationType, null, classValuesAsString, nestedAnnotationsAsMap));
AnnotationUtils.postProcessAnnotationAttributes(element, attributes, classValuesAsString, nestedAnnotationsAsMap);
return attributes;
}
/**
- * 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}.
+ * 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; never {@code null}
- * @param annotationName the fully qualified class name of the annotation
- * type to find; never {@code null} or empty
- * @return a {@link MultiValueMap} keyed by attribute name, containing
- * the annotation attributes from all annotations found, or {@code null}
- * if not found
+ * {@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 getAllAnnotationAttributes(AnnotatedElement element, String annotationName) {
@@ -460,31 +551,28 @@ public class AnnotatedElementUtils {
* 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; never {@code null}
- * @param annotationName the fully qualified class name of the annotation
- * type to find; never {@code null} or empty
- * @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
+ * {@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 getAllAnnotationAttributes(AnnotatedElement element,
final String annotationName, final boolean classValuesAsString, final boolean nestedAnnotationsAsMap) {
final MultiValueMap attributesMap = new LinkedMultiValueMap();
- searchWithGetSemantics(element, annotationName, new SimpleAnnotationProcessor() {
+ searchWithGetSemantics(element, null, annotationName, new SimpleAnnotationProcessor() {
@Override
public Void process(AnnotatedElement annotatedElement, Annotation annotation, int metaDepth) {
boolean found = annotation.annotationType().getName().equals(annotationName);
if (found) {
- AnnotationAttributes annotationAttributes = AnnotationUtils.getAnnotationAttributes(annotation,
- classValuesAsString, nestedAnnotationsAsMap);
+ AnnotationAttributes annotationAttributes = AnnotationUtils.getAnnotationAttributes(
+ annotation, classValuesAsString, nestedAnnotationsAsMap);
for (Map.Entry entry : annotationAttributes.entrySet()) {
attributesMap.add(entry.getKey(), entry.getValue());
}
@@ -500,15 +588,19 @@ public class AnnotatedElementUtils {
/**
* Search for annotations of the specified {@code annotationName} on
* the specified {@code element}, following get semantics.
- * @param element the annotated element; never {@code null}
+ * @param element the annotated element
+ * @param annotationType the annotation type on which to find meta-annotations
* @param annotationName the fully qualified class name of the annotation
- * type to find; never {@code null} or empty
+ * type to find (as an alternative to {@code annotationType})
* @param processor the processor to delegate to
* @return the result of the processor, potentially {@code null}
*/
- private static T searchWithGetSemantics(AnnotatedElement element, String annotationName, Processor processor) {
+ private static T searchWithGetSemantics(AnnotatedElement element,
+ Class extends Annotation> annotationType, String annotationName, Processor processor) {
+
try {
- return searchWithGetSemantics(element, annotationName, processor, new HashSet(), 0);
+ return searchWithGetSemantics(
+ element, annotationType, annotationName, processor, new HashSet(), 0);
}
catch (Throwable ex) {
AnnotationUtils.rethrowAnnotationConfigurationException(ex);
@@ -522,42 +614,45 @@ public class AnnotatedElementUtils {
* have already been visited.
* The {@code metaDepth} parameter is explained in the
* {@link Processor#process process()} method of the {@link Processor} API.
- * @param element the annotated element; never {@code null}
+ * @param element the annotated element
+ * @param annotationType the annotation type on which to find meta-annotations
* @param annotationName the fully qualified class name of the annotation
- * type to find; never {@code null} or empty
+ * type to find (as an alternative to {@code annotationType})
* @param processor the processor to delegate to
* @param visited the set of annotated elements that have already been visited
* @param metaDepth the meta-depth of the annotation
* @return the result of the processor, potentially {@code null}
*/
- private static T searchWithGetSemantics(AnnotatedElement element, String annotationName,
+ private static T searchWithGetSemantics(AnnotatedElement element,
+ Class extends Annotation> annotationType, String annotationName,
Processor processor, Set visited, int metaDepth) {
Assert.notNull(element, "AnnotatedElement must not be null");
- Assert.hasLength(annotationName, "annotationName must not be null or empty");
if (visited.add(element)) {
try {
// Start searching within locally declared annotations
List declaredAnnotations = Arrays.asList(element.getDeclaredAnnotations());
- T result = searchWithGetSemanticsInAnnotations(element, declaredAnnotations, annotationName, processor,
- visited, metaDepth);
+ T result = searchWithGetSemanticsInAnnotations(element, declaredAnnotations,
+ annotationType, annotationName, processor, visited, metaDepth);
if (result != null) {
return result;
}
- List inheritedAnnotations = new ArrayList();
- for (Annotation annotation : element.getAnnotations()) {
- if (!declaredAnnotations.contains(annotation)) {
- inheritedAnnotations.add(annotation);
+ if (element instanceof Class) { // otherwise getAnnotations doesn't return anything new
+ List inheritedAnnotations = new ArrayList();
+ for (Annotation annotation : element.getAnnotations()) {
+ if (!declaredAnnotations.contains(annotation)) {
+ inheritedAnnotations.add(annotation);
+ }
}
- }
- // Continue searching within inherited annotations
- result = searchWithGetSemanticsInAnnotations(
- element, inheritedAnnotations, annotationName, processor, visited, metaDepth);
- if (result != null) {
- return result;
+ // Continue searching within inherited annotations
+ result = searchWithGetSemanticsInAnnotations(element, inheritedAnnotations,
+ annotationType, annotationName, processor, visited, metaDepth);
+ if (result != null) {
+ return result;
+ }
}
}
catch (Exception ex) {
@@ -570,7 +665,7 @@ public class AnnotatedElementUtils {
/**
* This method is invoked by
- * {@link #searchWithGetSemantics(AnnotatedElement, String, Processor, Set, int)}
+ * {@link #searchWithGetSemantics(AnnotatedElement, Class, String, Processor, Set, int)}
* to perform the actual search within the supplied list of annotations.
* This method should be invoked first with locally declared annotations
* and then subsequently with inherited annotations, thereby allowing
@@ -579,22 +674,26 @@ public class AnnotatedElementUtils {
* {@link Processor#process process()} method of the {@link Processor} API.
* @param annotatedElement the element that is annotated with the supplied
* annotations, used for contextual logging; may be {@code null} if unknown
- * @param annotations the annotations to search in; never {@code null}
+ * @param annotations the annotations to search in
+ * @param annotationType the annotation type on which to find meta-annotations
* @param annotationName the fully qualified class name of the annotation
- * type to find; never {@code null} or empty
+ * type to find (as an alternative to {@code annotationType})
* @param processor the processor to delegate to
* @param visited the set of annotated elements that have already been visited
* @param metaDepth the meta-depth of the annotation
* @return the result of the processor, potentially {@code null}
* @since 4.2
*/
- private static T searchWithGetSemanticsInAnnotations(AnnotatedElement annotatedElement, List annotations,
- String annotationName, Processor processor, Set visited, int metaDepth) {
+ private static T searchWithGetSemanticsInAnnotations(AnnotatedElement annotatedElement,
+ List annotations, Class extends Annotation> annotationType, String annotationName,
+ Processor processor, Set visited, int metaDepth) {
// Search in annotations
for (Annotation annotation : annotations) {
if (!AnnotationUtils.isInJavaLangAnnotationPackage(annotation) &&
- (annotation.annotationType().getName().equals(annotationName) || metaDepth > 0)) {
+ ((annotationType != null ? annotation.annotationType() == annotationType :
+ annotation.annotationType().getName().equals(annotationName)) ||
+ metaDepth > 0)) {
T result = processor.process(annotatedElement, annotation, metaDepth);
if (result != null) {
return result;
@@ -605,8 +704,8 @@ public class AnnotatedElementUtils {
// Recursively search in meta-annotations
for (Annotation annotation : annotations) {
if (!AnnotationUtils.isInJavaLangAnnotationPackage(annotation)) {
- T result = searchWithGetSemantics(
- annotation.annotationType(), annotationName, processor, visited, metaDepth + 1);
+ T result = searchWithGetSemantics(annotation.annotationType(), annotationType,
+ annotationName, processor, visited, metaDepth + 1);
if (result != null) {
processor.postProcess(annotatedElement, annotation, result);
return result;
@@ -620,16 +719,20 @@ public class AnnotatedElementUtils {
/**
* Search for annotations of the specified {@code annotationName} on
* the specified {@code element}, following find semantics.
- * @param element the annotated element; never {@code null}
+ * @param element the annotated element
+ * @param annotationType the annotation type on which to find meta-annotations
* @param annotationName the fully qualified class name of the annotation
- * type to find; never {@code null} or empty
+ * type to find (as an alternative to {@code annotationType})
* @param processor the processor to delegate to
* @return the result of the processor, potentially {@code null}
* @since 4.2
*/
- private static T searchWithFindSemantics(AnnotatedElement element, String annotationName, Processor processor) {
+ private static T searchWithFindSemantics(
+ AnnotatedElement element, Class extends Annotation> annotationType, String annotationName, Processor processor) {
+
try {
- return searchWithFindSemantics(element, annotationName, processor, new HashSet(), 0);
+ return searchWithFindSemantics(
+ element, annotationType, annotationName, processor, new HashSet(), 0);
}
catch (Throwable ex) {
AnnotationUtils.rethrowAnnotationConfigurationException(ex);
@@ -643,17 +746,18 @@ public class AnnotatedElementUtils {
* have already been visited.
* The {@code metaDepth} parameter is explained in the
* {@link Processor#process process()} method of the {@link Processor} API.
- * @param element the annotated element; never {@code null}
+ * @param element the annotated element
+ * @param annotationType the annotation type on which to find meta-annotations
* @param annotationName the fully qualified class name of the annotation
- * type to find; never {@code null} or empty
+ * type to find (as an alternative to {@code annotationType})
* @param processor the processor to delegate to
* @param visited the set of annotated elements that have already been visited
* @param metaDepth the meta-depth of the annotation
* @return the result of the processor, potentially {@code null}
* @since 4.2
*/
- private static T searchWithFindSemantics(AnnotatedElement element, String annotationName,
- Processor processor, Set visited, int metaDepth) {
+ private static T searchWithFindSemantics(AnnotatedElement element, Class extends Annotation> annotationType,
+ String annotationName, Processor processor, Set visited, int metaDepth) {
Assert.notNull(element, "AnnotatedElement must not be null");
Assert.hasLength(annotationName, "annotationName must not be null or empty");
@@ -665,8 +769,10 @@ public class AnnotatedElementUtils {
// Search in local annotations
for (Annotation annotation : annotations) {
- if (!AnnotationUtils.isInJavaLangAnnotationPackage(annotation)
- && (annotation.annotationType().getName().equals(annotationName) || metaDepth > 0)) {
+ if (!AnnotationUtils.isInJavaLangAnnotationPackage(annotation) &&
+ ((annotationType != null ? annotation.annotationType() == annotationType :
+ annotation.annotationType().getName().equals(annotationName)) ||
+ metaDepth > 0)) {
T result = processor.process(element, annotation, metaDepth);
if (result != null) {
return result;
@@ -677,8 +783,8 @@ public class AnnotatedElementUtils {
// Search in meta annotations on local annotations
for (Annotation annotation : annotations) {
if (!AnnotationUtils.isInJavaLangAnnotationPackage(annotation)) {
- T result = searchWithFindSemantics(annotation.annotationType(), annotationName, processor,
- visited, metaDepth + 1);
+ T result = searchWithFindSemantics(
+ annotation.annotationType(), annotationType, annotationName, processor, visited, metaDepth + 1);
if (result != null) {
processor.postProcess(annotation.annotationType(), annotation, result);
return result;
@@ -691,14 +797,16 @@ public class AnnotatedElementUtils {
// Search on possibly bridged method
Method resolvedMethod = BridgeMethodResolver.findBridgedMethod(method);
- T result = searchWithFindSemantics(resolvedMethod, annotationName, processor, visited, metaDepth);
+ T result = searchWithFindSemantics(resolvedMethod, annotationType, annotationName,
+ processor, visited, metaDepth);
if (result != null) {
return result;
}
// Search on methods in interfaces declared locally
Class>[] ifcs = method.getDeclaringClass().getInterfaces();
- result = searchOnInterfaces(method, annotationName, processor, visited, metaDepth, ifcs);
+ result = searchOnInterfaces(
+ method, annotationType, annotationName, processor, visited, metaDepth, ifcs);
if (result != null) {
return result;
}
@@ -714,8 +822,8 @@ public class AnnotatedElementUtils {
try {
Method equivalentMethod = clazz.getDeclaredMethod(method.getName(), method.getParameterTypes());
Method resolvedEquivalentMethod = BridgeMethodResolver.findBridgedMethod(equivalentMethod);
- result = searchWithFindSemantics(
- resolvedEquivalentMethod, annotationName, processor, visited, metaDepth);
+ result = searchWithFindSemantics(resolvedEquivalentMethod, annotationType, annotationName,
+ processor, visited, metaDepth);
if (result != null) {
return result;
}
@@ -725,8 +833,8 @@ public class AnnotatedElementUtils {
}
// Search on interfaces declared on superclass
- result = searchOnInterfaces(method, annotationName, processor, visited, metaDepth,
- clazz.getInterfaces());
+ result = searchOnInterfaces(method, annotationType, annotationName, processor, visited,
+ metaDepth, clazz.getInterfaces());
if (result != null) {
return result;
}
@@ -738,7 +846,8 @@ public class AnnotatedElementUtils {
// Search on interfaces
for (Class> ifc : clazz.getInterfaces()) {
- T result = searchWithFindSemantics(ifc, annotationName, processor, visited, metaDepth);
+ T result = searchWithFindSemantics(
+ ifc, annotationType, annotationName, processor, visited, metaDepth);
if (result != null) {
return result;
}
@@ -747,7 +856,8 @@ public class AnnotatedElementUtils {
// Search on superclass
Class> superclass = clazz.getSuperclass();
if (superclass != null && Object.class != superclass) {
- T result = searchWithFindSemantics(superclass, annotationName, processor, visited, metaDepth);
+ T result = searchWithFindSemantics(
+ superclass, annotationType, annotationName, processor, visited, metaDepth);
if (result != null) {
return result;
}
@@ -761,14 +871,15 @@ public class AnnotatedElementUtils {
return null;
}
- private static T searchOnInterfaces(Method method, String annotationName, Processor processor,
- Set visited, int metaDepth, Class>[] ifcs) {
+ private static T searchOnInterfaces(Method method, Class extends Annotation> annotationType, String annotationName,
+ Processor processor, Set visited, int metaDepth, Class>[] ifcs) {
for (Class> iface : ifcs) {
if (AnnotationUtils.isInterfaceWithAnnotatedMethods(iface)) {
try {
Method equivalentMethod = iface.getMethod(method.getName(), method.getParameterTypes());
- T result = searchWithFindSemantics(equivalentMethod, annotationName, processor, visited, metaDepth);
+ T result = searchWithFindSemantics(equivalentMethod, annotationType, annotationName,
+ processor, visited, metaDepth);
if (result != null) {
return result;
}
@@ -871,15 +982,18 @@ public class AnnotatedElementUtils {
*/
private static class MergedAnnotationAttributesProcessor implements Processor {
+ private final Class extends Annotation> annotationType;
+
private final String annotationName;
private final boolean classValuesAsString;
private final boolean nestedAnnotationsAsMap;
- MergedAnnotationAttributesProcessor(String annotationName, boolean classValuesAsString,
- boolean nestedAnnotationsAsMap) {
+ MergedAnnotationAttributesProcessor(Class extends Annotation> annotationType, String annotationName,
+ boolean classValuesAsString, boolean nestedAnnotationsAsMap) {
+ this.annotationType = annotationType;
this.annotationName = annotationName;
this.classValuesAsString = classValuesAsString;
this.nestedAnnotationsAsMap = nestedAnnotationsAsMap;
@@ -887,7 +1001,8 @@ public class AnnotatedElementUtils {
@Override
public AnnotationAttributes process(AnnotatedElement annotatedElement, Annotation annotation, int metaDepth) {
- boolean found = annotation.annotationType().getName().equals(this.annotationName);
+ boolean found = (this.annotationType != null ? annotation.annotationType() == this.annotationType :
+ annotation.annotationType().getName().equals(this.annotationName));
return (found ? AnnotationUtils.getAnnotationAttributes(annotatedElement, annotation,
this.classValuesAsString, this.nestedAnnotationsAsMap, true) : null);
}