diff --git a/spring-beans/src/main/java/org/springframework/beans/factory/annotation/AutowiredAnnotationBeanPostProcessor.java b/spring-beans/src/main/java/org/springframework/beans/factory/annotation/AutowiredAnnotationBeanPostProcessor.java index b610cbd6b9..2ac33ba559 100644 --- a/spring-beans/src/main/java/org/springframework/beans/factory/annotation/AutowiredAnnotationBeanPostProcessor.java +++ b/spring-beans/src/main/java/org/springframework/beans/factory/annotation/AutowiredAnnotationBeanPostProcessor.java @@ -442,7 +442,7 @@ public class AutowiredAnnotationBeanPostProcessor extends InstantiationAwareBean private AnnotationAttributes findAutowiredAnnotation(AccessibleObject ao) { for (Class type : this.autowiredAnnotationTypes) { - AnnotationAttributes attributes = AnnotatedElementUtils.getAnnotationAttributes(ao, type); + AnnotationAttributes attributes = AnnotatedElementUtils.getMergedAnnotationAttributes(ao, type); if (attributes != null) { return attributes; } diff --git a/spring-context/src/main/java/org/springframework/context/event/ApplicationListenerMethodAdapter.java b/spring-context/src/main/java/org/springframework/context/event/ApplicationListenerMethodAdapter.java index c37e8eb831..b113df69dd 100644 --- a/spring-context/src/main/java/org/springframework/context/event/ApplicationListenerMethodAdapter.java +++ b/spring-context/src/main/java/org/springframework/context/event/ApplicationListenerMethodAdapter.java @@ -248,7 +248,7 @@ public class ApplicationListenerMethodAdapter implements GenericApplicationListe */ protected String getCondition() { if (this.condition == null) { - EventListener eventListener = AnnotatedElementUtils.findAnnotation(this.method, EventListener.class); + EventListener eventListener = AnnotatedElementUtils.findMergedAnnotation(this.method, EventListener.class); if (eventListener != null) { this.condition = eventListener.condition(); } 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 d7b3617a22..8124166932 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 @@ -48,8 +48,9 @@ import org.springframework.util.StringUtils; *

Annotation Attribute Overrides

*

Support for meta-annotations with attribute overrides in * composed annotations is provided by all variants of the - * {@code getAnnotationAttributes()}, {@code findAnnotation()}, and - * {@code findAnnotationAttributes()} methods. + * {@code getMergedAnnotationAttributes()}, {@code getMergedAnnotation()}, + * {@code findMergedAnnotationAttributes()}, and {@code findMergedAnnotation()} + * methods. * *

Find vs. Get Semantics

*

The search algorithms used by methods in this class follow either @@ -59,7 +60,7 @@ import org.springframework.util.StringUtils; *

Get semantics are limited to searching for annotations * that are either present on an {@code AnnotatedElement} (i.e., * declared locally or {@linkplain java.lang.annotation.Inherited inherited}) - * or declared within the annotation hierarchy above an + * or declared within the annotation hierarchy above the * {@code AnnotatedElement}. * *

Find semantics are much more exhaustive, providing @@ -110,11 +111,11 @@ public class AnnotatedElementUtils { * meta-annotations; never {@code null} * @return the names of all meta-annotations present on the annotation, * or {@code null} if not found + * @since 4.2 * @see #getMetaAnnotationTypes(AnnotatedElement, String) * @see #hasMetaAnnotationTypes */ - public static Set getMetaAnnotationTypes(AnnotatedElement element, - Class annotationType) { + public static Set getMetaAnnotationTypes(AnnotatedElement element, Class annotationType) { Assert.notNull(annotationType, "annotationType must not be null"); return getMetaAnnotationTypes(element, annotationType.getName()); } @@ -122,29 +123,29 @@ public class AnnotatedElementUtils { /** * Get the fully qualified class names of all meta-annotation * types present on the annotation (of the specified - * {@code annotationType}) on the supplied {@link AnnotatedElement}. + * {@code annotationName}) on the supplied {@link AnnotatedElement}. * *

This method follows get semantics as described in the * {@linkplain AnnotatedElementUtils class-level Javadoc}. * * @param element the annotated element; never {@code null} - * @param annotationType the fully qualified class name of the annotation + * @param annotationName the fully qualified class name of the annotation * type on which to find meta-annotations; never {@code null} or empty * @return the names of all meta-annotations present on the annotation, * or {@code null} if not found * @see #getMetaAnnotationTypes(AnnotatedElement, Class) * @see #hasMetaAnnotationTypes */ - public static Set getMetaAnnotationTypes(AnnotatedElement element, String annotationType) { + public static Set getMetaAnnotationTypes(AnnotatedElement element, String annotationName) { Assert.notNull(element, "AnnotatedElement must not be null"); - Assert.hasText(annotationType, "annotationType must not be null or empty"); + Assert.hasText(annotationName, "annotationName must not be null or empty"); final Set types = new LinkedHashSet(); try { - Annotation annotation = getAnnotation(element, annotationType); + Annotation annotation = getAnnotation(element, annotationName); if (annotation != null) { - searchWithGetSemantics(annotation.annotationType(), annotationType, new SimpleAnnotationProcessor() { + searchWithGetSemantics(annotation.annotationType(), annotationName, new SimpleAnnotationProcessor() { @Override public Object process(AnnotatedElement annotatedElement, Annotation annotation, int metaDepth) { @@ -165,54 +166,54 @@ public class AnnotatedElementUtils { /** * Determine if the supplied {@link AnnotatedElement} is annotated with * a composed annotation that is meta-annotated with an - * annotation of the specified {@code annotationType}. + * annotation of the specified {@code annotationName}. * *

This method follows get semantics as described in the * {@linkplain AnnotatedElementUtils class-level Javadoc}. * * @param element the annotated element; never {@code null} - * @param annotationType the fully qualified class name of the meta-annotation + * @param annotationName the fully qualified class name of the meta-annotation * type to find; never {@code null} or empty * @return {@code true} if a matching meta-annotation is present * @see #getMetaAnnotationTypes */ - public static boolean hasMetaAnnotationTypes(AnnotatedElement element, final String annotationType) { + public static boolean hasMetaAnnotationTypes(AnnotatedElement element, final String annotationName) { Assert.notNull(element, "AnnotatedElement must not be null"); - Assert.hasText(annotationType, "annotationType must not be null or empty"); + Assert.hasText(annotationName, "annotationName must not be null or empty"); - return Boolean.TRUE.equals(searchWithGetSemantics(element, annotationType, new SimpleAnnotationProcessor() { + return Boolean.TRUE.equals(searchWithGetSemantics(element, annotationName, new SimpleAnnotationProcessor() { @Override public Boolean process(AnnotatedElement annotatedElement, Annotation annotation, int metaDepth) { - boolean found = annotation.annotationType().getName().equals(annotationType); + boolean found = annotation.annotationType().getName().equals(annotationName); return ((found && (metaDepth > 0)) ? Boolean.TRUE : CONTINUE); } })); } /** - * Determine if an annotation of the specified {@code annotationType} + * Determine if an annotation of the specified {@code annotationName} * is present on the supplied {@link AnnotatedElement} or * within the annotation hierarchy above the specified element. * - *

If this method returns {@code true}, then {@link #getAnnotationAttributes} + *

If this method returns {@code true}, then {@link #getMergedAnnotationAttributes} * will return a non-null value. * *

This method follows get semantics as described in the * {@linkplain AnnotatedElementUtils class-level Javadoc}. * * @param element the annotated element; never {@code null} - * @param annotationType the fully qualified class name of the annotation + * @param annotationName the fully qualified class name of the annotation * type to find; never {@code null} or empty * @return {@code true} if a matching annotation is present */ - public static boolean isAnnotated(AnnotatedElement element, final String annotationType) { + public static boolean isAnnotated(AnnotatedElement element, final String annotationName) { Assert.notNull(element, "AnnotatedElement must not be null"); - Assert.hasText(annotationType, "annotationType must not be null or empty"); + Assert.hasText(annotationName, "annotationName must not be null or empty"); - return Boolean.TRUE.equals(searchWithGetSemantics(element, annotationType, new SimpleAnnotationProcessor() { + return Boolean.TRUE.equals(searchWithGetSemantics(element, annotationName, new SimpleAnnotationProcessor() { @Override public Boolean process(AnnotatedElement annotatedElement, Annotation annotation, int metaDepth) { - boolean found = annotation.annotationType().getName().equals(annotationType); + boolean found = annotation.annotationType().getName().equals(annotationName); return (found ? Boolean.TRUE : CONTINUE); } })); @@ -228,19 +229,19 @@ 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 #getAnnotationAttributes(AnnotatedElement, Class)} + *

This method delegates to {@link #getMergedAnnotationAttributes(AnnotatedElement, Class)} * and {@link AnnotationUtils#synthesizeAnnotation(Map, Class, AnnotatedElement)}. * * @param element the annotated element; never {@code null} * @param annotationType the annotation type to find; never {@code null} - * @return the merged {@code AnnotationAttributes}, or {@code null} if not found + * @return the merged, synthesized {@code Annotation}, or {@code null} if not found * @since 4.2 - * @see #getAnnotationAttributes(AnnotatedElement, Class) - * @see #findAnnotation(AnnotatedElement, Class) + * @see #getMergedAnnotationAttributes(AnnotatedElement, Class) + * @see #findMergedAnnotation(AnnotatedElement, Class) * @see AnnotationUtils#synthesizeAnnotation(Map, Class, AnnotatedElement) */ - public static A getAnnotation(AnnotatedElement element, Class annotationType) { - AnnotationAttributes attributes = getAnnotationAttributes(element, annotationType); + public static A getMergedAnnotation(AnnotatedElement element, Class annotationType) { + AnnotationAttributes attributes = getMergedAnnotationAttributes(element, annotationType); return ((attributes != null) ? AnnotationUtils.synthesizeAnnotation(attributes, annotationType, element) : null); } @@ -253,25 +254,32 @@ 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 #getAnnotationAttributes(AnnotatedElement, String)}. + *

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} * @return the merged {@code AnnotationAttributes}, or {@code null} if not found * @since 4.2 - * @see #getAnnotationAttributes(AnnotatedElement, String, boolean, boolean) - * @see #findAnnotationAttributes(AnnotatedElement, String, boolean, boolean) - * @see #getAnnotation(AnnotatedElement, Class) - * @see #findAnnotation(AnnotatedElement, Class) + * @see #getMergedAnnotationAttributes(AnnotatedElement, String, boolean, boolean) + * @see #findMergedAnnotationAttributes(AnnotatedElement, String, boolean, boolean) + * @see #getMergedAnnotation(AnnotatedElement, Class) + * @see #findMergedAnnotation(AnnotatedElement, Class) */ - public static AnnotationAttributes getAnnotationAttributes(AnnotatedElement element, - Class annotationType) { + public static AnnotationAttributes getMergedAnnotationAttributes(AnnotatedElement element, Class annotationType) { Assert.notNull(annotationType, "annotationType must not be null"); - return getAnnotationAttributes(element, annotationType.getName()); + return getMergedAnnotationAttributes(element, annotationType.getName()); } /** - * Get the first annotation of the specified {@code annotationType} within + * @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); + } + + /** + * 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. @@ -279,25 +287,35 @@ 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 #getAnnotationAttributes(AnnotatedElement, String, boolean, boolean)}, + *

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 annotationType the fully qualified class name of the annotation + * @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 - * @see #getAnnotationAttributes(AnnotatedElement, String, boolean, boolean) - * @see #findAnnotationAttributes(AnnotatedElement, String, boolean, boolean) - * @see #findAnnotation(AnnotatedElement, Class) + * @since 4.2 + * @see #getMergedAnnotationAttributes(AnnotatedElement, String, boolean, boolean) + * @see #findMergedAnnotationAttributes(AnnotatedElement, String, boolean, boolean) + * @see #findMergedAnnotation(AnnotatedElement, Class) * @see #getAllAnnotationAttributes(AnnotatedElement, String) */ - public static AnnotationAttributes getAnnotationAttributes(AnnotatedElement element, String annotationType) { - return getAnnotationAttributes(element, annotationType, false, false); + public static AnnotationAttributes getMergedAnnotationAttributes(AnnotatedElement element, String annotationName) { + return getMergedAnnotationAttributes(element, annotationName, false, false); } /** - * Get the first annotation of the specified {@code annotationType} within + * @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. @@ -310,14 +328,14 @@ public class AnnotatedElementUtils { *

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. + * {@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 annotationType the fully qualified class name of the annotation + * @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 @@ -326,15 +344,16 @@ public class AnnotatedElementUtils { * as Annotation instances * @return the merged {@code AnnotationAttributes}, or {@code null} if * not found - * @see #findAnnotation(AnnotatedElement, Class) - * @see #findAnnotationAttributes(AnnotatedElement, String, boolean, boolean) + * @since 4.2 + * @see #findMergedAnnotation(AnnotatedElement, Class) + * @see #findMergedAnnotationAttributes(AnnotatedElement, String, boolean, boolean) * @see #getAllAnnotationAttributes(AnnotatedElement, String, boolean, boolean) */ - public static AnnotationAttributes getAnnotationAttributes(AnnotatedElement element, String annotationType, + public static AnnotationAttributes getMergedAnnotationAttributes(AnnotatedElement element, String annotationName, boolean classValuesAsString, boolean nestedAnnotationsAsMap) { - AnnotationAttributes attributes = searchWithGetSemantics(element, annotationType, - new MergedAnnotationAttributesProcessor(annotationType, classValuesAsString, nestedAnnotationsAsMap)); + AnnotationAttributes attributes = searchWithGetSemantics(element, annotationName, + new MergedAnnotationAttributesProcessor(annotationName, classValuesAsString, nestedAnnotationsAsMap)); AnnotationUtils.postProcessAnnotationAttributes(element, attributes, classValuesAsString, nestedAnnotationsAsMap); return attributes; @@ -350,53 +369,53 @@ 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 #findAnnotation(AnnotatedElement, String)}. + *

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} * @return the merged, synthesized {@code Annotation}, or {@code null} if not found * @since 4.2 - * @see #findAnnotation(AnnotatedElement, String) - * @see #findAnnotationAttributes(AnnotatedElement, String, boolean, boolean) - * @see #getAnnotationAttributes(AnnotatedElement, Class) + * @see #findMergedAnnotation(AnnotatedElement, String) + * @see #findMergedAnnotationAttributes(AnnotatedElement, String, boolean, boolean) + * @see #getMergedAnnotationAttributes(AnnotatedElement, Class) */ - public static A findAnnotation(AnnotatedElement element, Class annotationType) { + public static A findMergedAnnotation(AnnotatedElement element, Class annotationType) { Assert.notNull(annotationType, "annotationType must not be null"); - return findAnnotation(element, annotationType.getName()); + return findMergedAnnotation(element, annotationType.getName()); } /** - * Find the first annotation of the specified {@code annotationType} within + * Find the first annotation of the specified {@code annotationName} 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}. + * the result back into an annotation of the specified {@code annotationName}. * *

{@link AliasFor @AliasFor} semantics are fully supported, both * within a single annotation and within the annotation hierarchy. * - *

This method delegates to {@link #findAnnotationAttributes(AnnotatedElement, String, boolean, boolean)} + *

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 annotationType the fully qualified class name of the annotation + * @param annotationName the fully qualified class name of the annotation * type to find; never {@code null} or empty * @return the merged, synthesized {@code Annotation}, or {@code null} if not found * @since 4.2 - * @see #findAnnotation(AnnotatedElement, Class) - * @see #findAnnotationAttributes(AnnotatedElement, String, boolean, boolean) + * @see #findMergedAnnotation(AnnotatedElement, Class) + * @see #findMergedAnnotationAttributes(AnnotatedElement, String, boolean, boolean) * @see AnnotationUtils#synthesizeAnnotation(Map, Class, AnnotatedElement) */ @SuppressWarnings("unchecked") - public static A findAnnotation(AnnotatedElement element, String annotationType) { - AnnotationAttributes attributes = findAnnotationAttributes(element, annotationType, false, false); + public static A findMergedAnnotation(AnnotatedElement element, String annotationName) { + AnnotationAttributes attributes = findMergedAnnotationAttributes(element, annotationName, false, false); return ((attributes != null) ? AnnotationUtils.synthesizeAnnotation(attributes, (Class) attributes.annotationType(), element) : null); } /** - * Find the first annotation of the specified {@code annotationType} within + * 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. @@ -409,14 +428,14 @@ public class AnnotatedElementUtils { *

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. + * {@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 annotationType the fully qualified class name of the annotation + * @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 @@ -426,57 +445,57 @@ public class AnnotatedElementUtils { * @return the merged {@code AnnotationAttributes}, or {@code null} if * not found * @since 4.2 - * @see #findAnnotation(AnnotatedElement, Class) - * @see #getAnnotationAttributes(AnnotatedElement, String, boolean, boolean) + * @see #findMergedAnnotation(AnnotatedElement, Class) + * @see #getMergedAnnotationAttributes(AnnotatedElement, String, boolean, boolean) */ - public static AnnotationAttributes findAnnotationAttributes(AnnotatedElement element, String annotationType, + public static AnnotationAttributes findMergedAnnotationAttributes(AnnotatedElement element, String annotationName, boolean classValuesAsString, boolean nestedAnnotationsAsMap) { - AnnotationAttributes attributes = searchWithFindSemantics(element, annotationType, - new MergedAnnotationAttributesProcessor(annotationType, classValuesAsString, nestedAnnotationsAsMap)); + AnnotationAttributes attributes = searchWithFindSemantics(element, annotationName, + new MergedAnnotationAttributesProcessor(annotationName, classValuesAsString, nestedAnnotationsAsMap)); AnnotationUtils.postProcessAnnotationAttributes(element, attributes, classValuesAsString, nestedAnnotationsAsMap); return attributes; } /** - * Get the annotation attributes of all annotations - * of the specified {@code annotationType} in the annotation hierarchy above + * 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 #getAnnotationAttributes(AnnotatedElement, String)}, + *

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 annotationType the fully qualified class name of the annotation + * @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 * @see #getAllAnnotationAttributes(AnnotatedElement, String, boolean, boolean) */ - public static MultiValueMap getAllAnnotationAttributes(AnnotatedElement element, String annotationType) { - return getAllAnnotationAttributes(element, annotationType, false, false); + public static MultiValueMap getAllAnnotationAttributes(AnnotatedElement element, String annotationName) { + return getAllAnnotationAttributes(element, annotationName, false, false); } /** - * Get the annotation attributes of all annotations - * of the specified {@code annotationType} in the annotation hierarchy above + * 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 #getAnnotationAttributes(AnnotatedElement, String)}, + *

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 annotationType the fully qualified class name of the annotation + * @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 @@ -488,15 +507,15 @@ public class AnnotatedElementUtils { * if not found */ public static MultiValueMap getAllAnnotationAttributes(AnnotatedElement element, - final String annotationType, final boolean classValuesAsString, final boolean nestedAnnotationsAsMap) { + final String annotationName, final boolean classValuesAsString, final boolean nestedAnnotationsAsMap) { final MultiValueMap attributesMap = new LinkedMultiValueMap(); - searchWithGetSemantics(element, annotationType, new SimpleAnnotationProcessor() { + searchWithGetSemantics(element, annotationName, new SimpleAnnotationProcessor() { @Override public Void process(AnnotatedElement annotatedElement, Annotation annotation, int metaDepth) { - boolean found = annotation.annotationType().getName().equals(annotationType); + boolean found = annotation.annotationType().getName().equals(annotationName); if (found) { AnnotationAttributes annotationAttributes = AnnotationUtils.getAnnotationAttributes(annotation, classValuesAsString, nestedAnnotationsAsMap); @@ -514,18 +533,18 @@ public class AnnotatedElementUtils { } /** - * Search for annotations of the specified {@code annotationType} on + * 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 annotationType the fully qualified class name of the annotation + * @param annotationName the fully qualified class name of the annotation * type to find; never {@code null} or empty * @param processor the processor to delegate to * @return the result of the processor, potentially {@code null} */ - private static T searchWithGetSemantics(AnnotatedElement element, String annotationType, Processor processor) { + private static T searchWithGetSemantics(AnnotatedElement element, String annotationName, Processor processor) { try { - return searchWithGetSemantics(element, annotationType, processor, new HashSet(), 0); + return searchWithGetSemantics(element, annotationName, processor, new HashSet(), 0); } catch (Throwable ex) { AnnotationUtils.rethrowAnnotationConfigurationException(ex); @@ -543,25 +562,25 @@ public class AnnotatedElementUtils { * API. * * @param element the annotated element; never {@code null} - * @param annotationType the fully qualified class name of the annotation + * @param annotationName the fully qualified class name of the annotation * type to find; never {@code null} or empty * @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 annotationType, + private static T searchWithGetSemantics(AnnotatedElement element, String annotationName, Processor processor, Set visited, int metaDepth) { Assert.notNull(element, "AnnotatedElement must not be null"); - Assert.hasText(annotationType, "annotationType must not be null or empty"); + Assert.hasText(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, annotationType, processor, + T result = searchWithGetSemanticsInAnnotations(element, declaredAnnotations, annotationName, processor, visited, metaDepth); if (result != null) { return result; @@ -575,7 +594,7 @@ public class AnnotatedElementUtils { } // Continue searching within inherited annotations - result = searchWithGetSemanticsInAnnotations(element, inheritedAnnotations, annotationType, processor, + result = searchWithGetSemanticsInAnnotations(element, inheritedAnnotations, annotationName, processor, visited, metaDepth); if (result != null) { return result; @@ -593,6 +612,7 @@ public class AnnotatedElementUtils { * This method is invoked by * {@link #searchWithGetSemantics(AnnotatedElement, 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 * local annotations to take precedence over inherited annotations. @@ -604,21 +624,20 @@ public class AnnotatedElementUtils { * @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 annotationType the fully qualified class name of the annotation + * @param annotationName the fully qualified class name of the annotation * type to find; never {@code null} or empty * @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 searchWithGetSemanticsInAnnotations(AnnotatedElement annotatedElement, - List annotations, String annotationType, Processor processor, Set visited, - int metaDepth) { + private static T searchWithGetSemanticsInAnnotations(AnnotatedElement annotatedElement, List annotations, + String annotationName, Processor processor, Set visited, int metaDepth) { // Search in annotations for (Annotation annotation : annotations) { if (!AnnotationUtils.isInJavaLangAnnotationPackage(annotation) - && (annotation.annotationType().getName().equals(annotationType) || metaDepth > 0)) { + && (annotation.annotationType().getName().equals(annotationName) || metaDepth > 0)) { T result = processor.process(annotatedElement, annotation, metaDepth); if (result != null) { return result; @@ -629,7 +648,7 @@ public class AnnotatedElementUtils { // Recursively search in meta-annotations for (Annotation annotation : annotations) { if (!AnnotationUtils.isInJavaLangAnnotationPackage(annotation)) { - T result = searchWithGetSemantics(annotation.annotationType(), annotationType, processor, visited, + T result = searchWithGetSemantics(annotation.annotationType(), annotationName, processor, visited, metaDepth + 1); if (result != null) { processor.postProcess(annotatedElement, annotation, result); @@ -642,25 +661,25 @@ public class AnnotatedElementUtils { } /** - * Search for annotations of the specified {@code annotationType} on + * 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 annotationType the fully qualified class name of the annotation + * @param annotationName the fully qualified class name of the annotation * type to find; never {@code null} or empty * @param processor the processor to delegate to * @return the result of the processor, potentially {@code null} */ - private static T searchWithFindSemantics(AnnotatedElement element, String annotationType, Processor processor) { - return searchWithFindSemantics(element, annotationType, true, true, true, true, processor); + private static T searchWithFindSemantics(AnnotatedElement element, String annotationName, Processor processor) { + return searchWithFindSemantics(element, annotationName, true, true, true, true, processor); } /** - * Search for annotations of the specified {@code annotationType} on + * 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 annotationType the fully qualified class name of the annotation + * @param annotationName the fully qualified class name of the annotation * type to find; never {@code null} or empty * @param searchOnInterfaces whether to search on interfaces, if the * annotated element is a class @@ -673,12 +692,12 @@ public class AnnotatedElementUtils { * @param processor the processor to delegate to * @return the result of the processor, potentially {@code null} */ - private static T searchWithFindSemantics(AnnotatedElement element, String annotationType, + private static T searchWithFindSemantics(AnnotatedElement element, String annotationName, boolean searchOnInterfaces, boolean searchOnSuperclasses, boolean searchOnMethodsInInterfaces, boolean searchOnMethodsInSuperclasses, Processor processor) { try { - return searchWithFindSemantics(element, annotationType, searchOnInterfaces, searchOnSuperclasses, + return searchWithFindSemantics(element, annotationName, searchOnInterfaces, searchOnSuperclasses, searchOnMethodsInInterfaces, searchOnMethodsInSuperclasses, processor, new HashSet(), 0); } catch (Throwable ex) { @@ -697,7 +716,7 @@ public class AnnotatedElementUtils { * API. * * @param element the annotated element; never {@code null} - * @param annotationType the fully qualified class name of the annotation + * @param annotationName the fully qualified class name of the annotation * type to find; never {@code null} or empty * @param searchOnInterfaces whether to search on interfaces, if the * annotated element is a class @@ -712,12 +731,12 @@ public class AnnotatedElementUtils { * @param metaDepth the meta-depth of the annotation * @return the result of the processor, potentially {@code null} */ - private static T searchWithFindSemantics(AnnotatedElement element, String annotationType, + private static T searchWithFindSemantics(AnnotatedElement element, String annotationName, boolean searchOnInterfaces, boolean searchOnSuperclasses, boolean searchOnMethodsInInterfaces, boolean searchOnMethodsInSuperclasses, Processor processor, Set visited, int metaDepth) { Assert.notNull(element, "AnnotatedElement must not be null"); - Assert.hasText(annotationType, "annotationType must not be null or empty"); + Assert.hasText(annotationName, "annotationName must not be null or empty"); if (visited.add(element)) { try { @@ -729,7 +748,7 @@ public class AnnotatedElementUtils { // Search in local annotations for (Annotation annotation : annotations) { if (!AnnotationUtils.isInJavaLangAnnotationPackage(annotation) - && (annotation.annotationType().getName().equals(annotationType) || metaDepth > 0)) { + && (annotation.annotationType().getName().equals(annotationName) || metaDepth > 0)) { T result = processor.process(element, annotation, metaDepth); if (result != null) { return result; @@ -740,7 +759,7 @@ public class AnnotatedElementUtils { // Search in meta annotations on local annotations for (Annotation annotation : annotations) { if (!AnnotationUtils.isInJavaLangAnnotationPackage(annotation)) { - T result = searchWithFindSemantics(annotation.annotationType(), annotationType, + T result = searchWithFindSemantics(annotation.annotationType(), annotationName, searchOnInterfaces, searchOnSuperclasses, searchOnMethodsInInterfaces, searchOnMethodsInSuperclasses, processor, visited, metaDepth + 1); if (result != null) { @@ -755,7 +774,7 @@ public class AnnotatedElementUtils { // Search on possibly bridged method Method resolvedMethod = BridgeMethodResolver.findBridgedMethod(method); - T result = searchWithFindSemantics(resolvedMethod, annotationType, searchOnInterfaces, + T result = searchWithFindSemantics(resolvedMethod, annotationName, searchOnInterfaces, searchOnSuperclasses, searchOnMethodsInInterfaces, searchOnMethodsInSuperclasses, processor, visited, metaDepth); if (result != null) { @@ -765,9 +784,8 @@ public class AnnotatedElementUtils { // Search on methods in interfaces declared locally if (searchOnMethodsInInterfaces) { Class[] ifcs = method.getDeclaringClass().getInterfaces(); - result = searchOnInterfaces(method, annotationType, searchOnInterfaces, searchOnSuperclasses, - searchOnMethodsInInterfaces, searchOnMethodsInSuperclasses, processor, visited, metaDepth, - ifcs); + result = searchOnInterfaces(method, annotationName, searchOnInterfaces, searchOnSuperclasses, + searchOnMethodsInInterfaces, searchOnMethodsInSuperclasses, processor, visited, metaDepth, ifcs); if (result != null) { return result; } @@ -786,7 +804,7 @@ public class AnnotatedElementUtils { Method equivalentMethod = clazz.getDeclaredMethod(method.getName(), method.getParameterTypes()); Method resolvedEquivalentMethod = BridgeMethodResolver.findBridgedMethod(equivalentMethod); - result = searchWithFindSemantics(resolvedEquivalentMethod, annotationType, + result = searchWithFindSemantics(resolvedEquivalentMethod, annotationName, searchOnInterfaces, searchOnSuperclasses, searchOnMethodsInInterfaces, searchOnMethodsInSuperclasses, processor, visited, metaDepth); if (result != null) { @@ -799,7 +817,7 @@ public class AnnotatedElementUtils { // Search on interfaces declared on superclass if (searchOnMethodsInInterfaces) { - result = searchOnInterfaces(method, annotationType, searchOnInterfaces, + result = searchOnInterfaces(method, annotationName, searchOnInterfaces, searchOnSuperclasses, searchOnMethodsInInterfaces, searchOnMethodsInSuperclasses, processor, visited, metaDepth, clazz.getInterfaces()); if (result != null) { @@ -816,7 +834,7 @@ public class AnnotatedElementUtils { // Search on interfaces if (searchOnInterfaces) { for (Class ifc : clazz.getInterfaces()) { - T result = searchWithFindSemantics(ifc, annotationType, searchOnInterfaces, + T result = searchWithFindSemantics(ifc, annotationName, searchOnInterfaces, searchOnSuperclasses, searchOnMethodsInInterfaces, searchOnMethodsInSuperclasses, processor, visited, metaDepth); if (result != null) { @@ -829,7 +847,7 @@ public class AnnotatedElementUtils { if (searchOnSuperclasses) { Class superclass = clazz.getSuperclass(); if (superclass != null && Object.class != superclass) { - T result = searchWithFindSemantics(superclass, annotationType, searchOnInterfaces, + T result = searchWithFindSemantics(superclass, annotationName, searchOnInterfaces, searchOnSuperclasses, searchOnMethodsInInterfaces, searchOnMethodsInSuperclasses, processor, visited, metaDepth); if (result != null) { @@ -846,7 +864,7 @@ public class AnnotatedElementUtils { return null; } - private static T searchOnInterfaces(Method method, String annotationType, boolean searchOnInterfaces, + private static T searchOnInterfaces(Method method, String annotationName, boolean searchOnInterfaces, boolean searchOnSuperclasses, boolean searchOnMethodsInInterfaces, boolean searchOnMethodsInSuperclasses, Processor processor, Set visited, int metaDepth, Class[] ifcs) { @@ -854,7 +872,7 @@ public class AnnotatedElementUtils { if (AnnotationUtils.isInterfaceWithAnnotatedMethods(iface)) { try { Method equivalentMethod = iface.getMethod(method.getName(), method.getParameterTypes()); - T result = searchWithFindSemantics(equivalentMethod, annotationType, searchOnInterfaces, + T result = searchWithFindSemantics(equivalentMethod, annotationName, searchOnInterfaces, searchOnSuperclasses, searchOnMethodsInInterfaces, searchOnMethodsInSuperclasses, processor, visited, metaDepth); @@ -871,9 +889,9 @@ public class AnnotatedElementUtils { return null; } - private static Annotation getAnnotation(AnnotatedElement element, String annotationType) { + private static Annotation getAnnotation(AnnotatedElement element, String annotationName) { for (Annotation annotation : element.getAnnotations()) { - if (annotation.annotationType().getName().equals(annotationType)) { + if (annotation.annotationType().getName().equals(annotationName)) { return annotation; } } @@ -953,7 +971,7 @@ public class AnnotatedElementUtils { /** * {@link Processor} that {@linkplain #process processes} annotations - * but does not {@link #postProcess} results. + * but does not {@linkplain #postProcess post-process} results. * @since 4.2 */ private abstract static class SimpleAnnotationProcessor implements Processor { @@ -978,21 +996,21 @@ public class AnnotatedElementUtils { */ private static class MergedAnnotationAttributesProcessor implements Processor { - private final String annotationTypeName; + private final String annotationName; private final boolean classValuesAsString; private final boolean nestedAnnotationsAsMap; - MergedAnnotationAttributesProcessor(String annotationType, boolean classValuesAsString, + MergedAnnotationAttributesProcessor(String annotationName, boolean classValuesAsString, boolean nestedAnnotationsAsMap) { - this.annotationTypeName = annotationType; + this.annotationName = annotationName; this.classValuesAsString = classValuesAsString; this.nestedAnnotationsAsMap = nestedAnnotationsAsMap; } @Override public AnnotationAttributes process(AnnotatedElement annotatedElement, Annotation annotation, int metaDepth) { - boolean found = annotation.annotationType().getName().equals(this.annotationTypeName); + boolean found = annotation.annotationType().getName().equals(this.annotationName); return (found ? AnnotationUtils.getAnnotationAttributes(annotatedElement, annotation, this.classValuesAsString, this.nestedAnnotationsAsMap, true) : null); } diff --git a/spring-core/src/main/java/org/springframework/core/annotation/AnnotationUtils.java b/spring-core/src/main/java/org/springframework/core/annotation/AnnotationUtils.java index ab014d3fe8..bddd71e155 100644 --- a/spring-core/src/main/java/org/springframework/core/annotation/AnnotationUtils.java +++ b/spring-core/src/main/java/org/springframework/core/annotation/AnnotationUtils.java @@ -1024,10 +1024,10 @@ public abstract class AnnotationUtils { } /** - * Synthesize the supplied {@code annotation} by wrapping it in - * a dynamic proxy that transparently enforces attribute alias - * semantics for annotation attributes that are annotated with - * {@link AliasFor @AliasFor}. + * Synthesize an annotation from the supplied {@code annotation} + * by wrapping it in a dynamic proxy that transparently enforces + * attribute alias semantics for annotation attributes that are + * annotated with {@link AliasFor @AliasFor}. * * @param annotation the annotation to synthesize * @return the synthesized annotation, if the supplied annotation is @@ -1043,10 +1043,10 @@ public abstract class AnnotationUtils { } /** - * Synthesize the supplied {@code annotation} by wrapping it in - * a dynamic proxy that transparently enforces attribute alias - * semantics for annotation attributes that are annotated with - * {@link AliasFor @AliasFor}. + * Synthesize an annotation from the supplied {@code annotation} + * by wrapping it in a dynamic proxy that transparently enforces + * attribute alias semantics for annotation attributes that are + * annotated with {@link AliasFor @AliasFor}. * * @param annotation the annotation to synthesize * @param annotatedElement the element that is annotated with the supplied @@ -1083,15 +1083,15 @@ public abstract class AnnotationUtils { } /** - * Synthesize the supplied map of annotation attributes by - * wrapping it in a dynamic proxy that implements an annotation of type - * {@code annotationType} and transparently enforces attribute alias - * semantics for annotation attributes that are annotated with - * {@link AliasFor @AliasFor}. + * Synthesize an annotation from the supplied map of annotation + * attributes by wrapping the map in a dynamic proxy that implements an + * annotation of the specified {@code annotationType} and transparently + * enforces attribute alias semantics for annotation attributes + * that are annotated with {@link AliasFor @AliasFor}. *

The supplied map must contain key-value pairs for every attribute * defined by the supplied {@code annotationType}. *

Note that {@link AnnotationAttributes} is a specialized type of - * {@link Map} that is a suitable candidate for this method's + * {@link Map} that is an ideal candidate for this method's * {@code attributes} argument. * * @param attributes the map of annotation attributes to synthesize diff --git a/spring-core/src/main/java/org/springframework/core/type/AnnotatedTypeMetadata.java b/spring-core/src/main/java/org/springframework/core/type/AnnotatedTypeMetadata.java index be7e31d2c3..29541e8bb1 100644 --- a/spring-core/src/main/java/org/springframework/core/type/AnnotatedTypeMetadata.java +++ b/spring-core/src/main/java/org/springframework/core/type/AnnotatedTypeMetadata.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2014 the original author or authors. + * Copyright 2002-2015 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -42,27 +42,30 @@ public interface AnnotatedTypeMetadata { * of the given type defined. *

If this method returns {@code true}, then * {@link #getAnnotationAttributes} will return a non-null Map. - * @param annotationType the annotation type to look for + * @param annotationName the fully qualified class name of the annotation + * type to look for * @return whether a matching annotation is defined */ - boolean isAnnotated(String annotationType); + boolean isAnnotated(String annotationName); /** * Retrieve the attributes of the annotation of the given type, if any (i.e. if * defined on the underlying element, as direct annotation or meta-annotation), * also taking attribute overrides on composed annotations into account. - * @param annotationType the annotation type to look for + * @param annotationName the fully qualified class name of the annotation + * type to look for * @return a Map of attributes, with the attribute name as key (e.g. "value") * and the defined attribute value as Map value. This return value will be * {@code null} if no matching annotation is defined. */ - Map getAnnotationAttributes(String annotationType); + Map getAnnotationAttributes(String annotationName); /** * Retrieve the attributes of the annotation of the given type, if any (i.e. if * defined on the underlying element, as direct annotation or meta-annotation), * also taking attribute overrides on composed annotations into account. - * @param annotationType the annotation type to look for + * @param annotationName the fully qualified class name of the annotation + * type to look for * @param classValuesAsString whether to convert class references to String * class names for exposure as values in the returned Map, instead of Class * references which might potentially have to be loaded first @@ -70,31 +73,33 @@ public interface AnnotatedTypeMetadata { * and the defined attribute value as Map value. This return value will be * {@code null} if no matching annotation is defined. */ - Map getAnnotationAttributes(String annotationType, boolean classValuesAsString); + Map getAnnotationAttributes(String annotationName, boolean classValuesAsString); /** * Retrieve all attributes of all annotations of the given type, if any (i.e. if * defined on the underlying element, as direct annotation or meta-annotation). * Note that this variant does not take attribute overrides into account. - * @param annotationType the annotation type to look for + * @param annotationName the fully qualified class name of the annotation + * type to look for * @return a MultiMap of attributes, with the attribute name as key (e.g. "value") * and a list of the defined attribute values as Map value. This return value will * be {@code null} if no matching annotation is defined. * @see #getAllAnnotationAttributes(String, boolean) */ - MultiValueMap getAllAnnotationAttributes(String annotationType); + MultiValueMap getAllAnnotationAttributes(String annotationName); /** * Retrieve all attributes of all annotations of the given type, if any (i.e. if * defined on the underlying element, as direct annotation or meta-annotation). * Note that this variant does not take attribute overrides into account. - * @param annotationType the annotation type to look for + * @param annotationName the fully qualified class name of the annotation + * type to look for * @param classValuesAsString whether to convert class references to String * @return a MultiMap of attributes, with the attribute name as key (e.g. "value") * and a list of the defined attribute values as Map value. This return value will * be {@code null} if no matching annotation is defined. * @see #getAllAnnotationAttributes(String) */ - MultiValueMap getAllAnnotationAttributes(String annotationType, boolean classValuesAsString); + MultiValueMap getAllAnnotationAttributes(String annotationName, boolean classValuesAsString); } diff --git a/spring-core/src/main/java/org/springframework/core/type/AnnotationMetadata.java b/spring-core/src/main/java/org/springframework/core/type/AnnotationMetadata.java index 8c2ef4ca10..a8ae55bc15 100644 --- a/spring-core/src/main/java/org/springframework/core/type/AnnotationMetadata.java +++ b/spring-core/src/main/java/org/springframework/core/type/AnnotationMetadata.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2014 the original author or authors. + * Copyright 2002-2015 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -34,52 +34,58 @@ import java.util.Set; public interface AnnotationMetadata extends ClassMetadata, AnnotatedTypeMetadata { /** - * Return the names of all annotation types that are present on the - * underlying class. + * Get the fully qualified class names of all annotation types that + * are present on the underlying class. * @return the annotation type names */ Set getAnnotationTypes(); /** - * Return the names of all meta-annotation types present on the - * given annotation type on the underlying class. - * @param annotationType the meta-annotation type to look for + * Get the fully qualified class names of all meta-annotation types that + * are present on the given annotation type on the underlying class. + * @param annotationName the fully qualified class name of the meta-annotation + * type to look for * @return the meta-annotation type names */ - Set getMetaAnnotationTypes(String annotationType); + Set getMetaAnnotationTypes(String annotationName); /** * Determine whether an annotation of the given type is present on * the underlying class. - * @param annotationType the annotation type to look for - * @return whether a matching annotation is present + * @param annotationName the fully qualified class name of the annotation + * type to look for + * @return {@code true} if a matching annotation is present */ - boolean hasAnnotation(String annotationType); + boolean hasAnnotation(String annotationName); /** * Determine whether the underlying class has an annotation that is itself * annotated with the meta-annotation of the given type. - * @param metaAnnotationType the meta-annotation type to look for - * @return whether a matching meta-annotation is present + * @param metaAnnotationName the fully qualified class name of the + * meta-annotation type to look for + * @return {@code true} if a matching meta-annotation is present */ - boolean hasMetaAnnotation(String metaAnnotationType); + boolean hasMetaAnnotation(String metaAnnotationName); /** * Determine whether the underlying class has any methods that are * annotated (or meta-annotated) with the given annotation type. + * @param annotationName the fully qualified class name of the annotation + * type to look for */ - boolean hasAnnotatedMethods(String annotationType); + boolean hasAnnotatedMethods(String annotationName); /** * Retrieve the method metadata for all methods that are annotated * (or meta-annotated) with the given annotation type. *

For any returned method, {@link MethodMetadata#isAnnotated} will * return {@code true} for the given annotation type. - * @param annotationType the annotation type to look for + * @param annotationName the fully qualified class name of the annotation + * type to look for * @return a set of {@link MethodMetadata} for methods that have a matching * annotation. The return value will be an empty set if no methods match * the annotation type. */ - Set getAnnotatedMethods(String annotationType); + Set getAnnotatedMethods(String annotationName); } diff --git a/spring-core/src/main/java/org/springframework/core/type/StandardAnnotationMetadata.java b/spring-core/src/main/java/org/springframework/core/type/StandardAnnotationMetadata.java index cc2a86ce09..f98bbdd890 100644 --- a/spring-core/src/main/java/org/springframework/core/type/StandardAnnotationMetadata.java +++ b/spring-core/src/main/java/org/springframework/core/type/StandardAnnotationMetadata.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2014 the original author or authors. + * Copyright 2002-2015 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -33,6 +33,7 @@ import org.springframework.util.MultiValueMap; * @author Mark Fisher * @author Chris Beams * @author Phillip Webb + * @author Sam Brannen * @since 2.5 */ public class StandardAnnotationMetadata extends StandardClassMetadata implements AnnotationMetadata { @@ -77,15 +78,15 @@ public class StandardAnnotationMetadata extends StandardClassMetadata implements } @Override - public Set getMetaAnnotationTypes(String annotationType) { - return AnnotatedElementUtils.getMetaAnnotationTypes(getIntrospectedClass(), annotationType); + public Set getMetaAnnotationTypes(String annotationName) { + return AnnotatedElementUtils.getMetaAnnotationTypes(getIntrospectedClass(), annotationName); } @Override - public boolean hasAnnotation(String annotationType) { + public boolean hasAnnotation(String annotationName) { Annotation[] anns = getIntrospectedClass().getAnnotations(); for (Annotation ann : anns) { - if (ann.annotationType().getName().equals(annotationType)) { + if (ann.annotationType().getName().equals(annotationName)) { return true; } } @@ -93,42 +94,42 @@ public class StandardAnnotationMetadata extends StandardClassMetadata implements } @Override - public boolean hasMetaAnnotation(String annotationType) { - return AnnotatedElementUtils.hasMetaAnnotationTypes(getIntrospectedClass(), annotationType); + public boolean hasMetaAnnotation(String annotationName) { + return AnnotatedElementUtils.hasMetaAnnotationTypes(getIntrospectedClass(), annotationName); } @Override - public boolean isAnnotated(String annotationType) { - return AnnotatedElementUtils.isAnnotated(getIntrospectedClass(), annotationType); + public boolean isAnnotated(String annotationName) { + return AnnotatedElementUtils.isAnnotated(getIntrospectedClass(), annotationName); } @Override - public Map getAnnotationAttributes(String annotationType) { - return this.getAnnotationAttributes(annotationType, false); + public Map getAnnotationAttributes(String annotationName) { + return this.getAnnotationAttributes(annotationName, false); } @Override - public Map getAnnotationAttributes(String annotationType, boolean classValuesAsString) { - return AnnotatedElementUtils.getAnnotationAttributes(getIntrospectedClass(), - annotationType, classValuesAsString, this.nestedAnnotationsAsMap); + public Map getAnnotationAttributes(String annotationName, boolean classValuesAsString) { + return AnnotatedElementUtils.getMergedAnnotationAttributes(getIntrospectedClass(), + annotationName, classValuesAsString, this.nestedAnnotationsAsMap); } @Override - public MultiValueMap getAllAnnotationAttributes(String annotationType) { - return getAllAnnotationAttributes(annotationType, false); + public MultiValueMap getAllAnnotationAttributes(String annotationName) { + return getAllAnnotationAttributes(annotationName, false); } @Override - public MultiValueMap getAllAnnotationAttributes(String annotationType, boolean classValuesAsString) { + public MultiValueMap getAllAnnotationAttributes(String annotationName, boolean classValuesAsString) { return AnnotatedElementUtils.getAllAnnotationAttributes(getIntrospectedClass(), - annotationType, classValuesAsString, this.nestedAnnotationsAsMap); + annotationName, classValuesAsString, this.nestedAnnotationsAsMap); } @Override - public boolean hasAnnotatedMethods(String annotationType) { + public boolean hasAnnotatedMethods(String annotationName) { Method[] methods = getIntrospectedClass().getDeclaredMethods(); for (Method method : methods) { - if (!method.isBridge() && AnnotatedElementUtils.isAnnotated(method, annotationType)) { + if (!method.isBridge() && AnnotatedElementUtils.isAnnotated(method, annotationName)) { return true; } } @@ -136,11 +137,11 @@ public class StandardAnnotationMetadata extends StandardClassMetadata implements } @Override - public Set getAnnotatedMethods(String annotationType) { + public Set getAnnotatedMethods(String annotationName) { Method[] methods = getIntrospectedClass().getDeclaredMethods(); Set annotatedMethods = new LinkedHashSet(); for (Method method : methods) { - if (!method.isBridge() && AnnotatedElementUtils.isAnnotated(method, annotationType)) { + if (!method.isBridge() && AnnotatedElementUtils.isAnnotated(method, annotationName)) { annotatedMethods.add(new StandardMethodMetadata(method, this.nestedAnnotationsAsMap)); } } diff --git a/spring-core/src/main/java/org/springframework/core/type/StandardMethodMetadata.java b/spring-core/src/main/java/org/springframework/core/type/StandardMethodMetadata.java index 65c7d716b1..dbb6fe2837 100644 --- a/spring-core/src/main/java/org/springframework/core/type/StandardMethodMetadata.java +++ b/spring-core/src/main/java/org/springframework/core/type/StandardMethodMetadata.java @@ -73,7 +73,6 @@ public class StandardMethodMetadata implements MethodMetadata { return this.introspectedMethod; } - @Override public String getMethodName() { return this.introspectedMethod.getName(); @@ -110,30 +109,30 @@ public class StandardMethodMetadata implements MethodMetadata { } @Override - public boolean isAnnotated(String annotationType) { - return AnnotatedElementUtils.isAnnotated(this.introspectedMethod, annotationType); + public boolean isAnnotated(String annotationName) { + return AnnotatedElementUtils.isAnnotated(this.introspectedMethod, annotationName); } @Override - public Map getAnnotationAttributes(String annotationType) { - return getAnnotationAttributes(annotationType, false); + public Map getAnnotationAttributes(String annotationName) { + return getAnnotationAttributes(annotationName, false); } @Override - public Map getAnnotationAttributes(String annotationType, boolean classValuesAsString) { - return AnnotatedElementUtils.getAnnotationAttributes(this.introspectedMethod, - annotationType, classValuesAsString, this.nestedAnnotationsAsMap); + public Map getAnnotationAttributes(String annotationName, boolean classValuesAsString) { + return AnnotatedElementUtils.getMergedAnnotationAttributes(this.introspectedMethod, + annotationName, classValuesAsString, this.nestedAnnotationsAsMap); } @Override - public MultiValueMap getAllAnnotationAttributes(String annotationType) { - return getAllAnnotationAttributes(annotationType, false); + public MultiValueMap getAllAnnotationAttributes(String annotationName) { + return getAllAnnotationAttributes(annotationName, false); } @Override - public MultiValueMap getAllAnnotationAttributes(String annotationType, boolean classValuesAsString) { + public MultiValueMap getAllAnnotationAttributes(String annotationName, boolean classValuesAsString) { return AnnotatedElementUtils.getAllAnnotationAttributes(this.introspectedMethod, - annotationType, classValuesAsString, this.nestedAnnotationsAsMap); + annotationName, classValuesAsString, this.nestedAnnotationsAsMap); } } diff --git a/spring-core/src/main/java/org/springframework/core/type/classreading/AnnotationMetadataReadingVisitor.java b/spring-core/src/main/java/org/springframework/core/type/classreading/AnnotationMetadataReadingVisitor.java index 3352e5c6e3..e733c06d77 100644 --- a/spring-core/src/main/java/org/springframework/core/type/classreading/AnnotationMetadataReadingVisitor.java +++ b/spring-core/src/main/java/org/springframework/core/type/classreading/AnnotationMetadataReadingVisitor.java @@ -94,13 +94,13 @@ public class AnnotationMetadataReadingVisitor extends ClassMetadataReadingVisito } @Override - public Set getMetaAnnotationTypes(String annotationType) { - return this.metaAnnotationMap.get(annotationType); + public Set getMetaAnnotationTypes(String annotationName) { + return this.metaAnnotationMap.get(annotationName); } @Override - public boolean hasAnnotation(String annotationType) { - return this.annotationSet.contains(annotationType); + public boolean hasAnnotation(String annotationName) { + return this.annotationSet.contains(annotationName); } @Override @@ -115,31 +115,32 @@ public class AnnotationMetadataReadingVisitor extends ClassMetadataReadingVisito } @Override - public boolean isAnnotated(String annotationType) { - return (!AnnotationUtils.isInJavaLangAnnotationPackage(annotationType) && this.attributesMap.containsKey(annotationType)); + public boolean isAnnotated(String annotationName) { + return (!AnnotationUtils.isInJavaLangAnnotationPackage(annotationName) && this.attributesMap.containsKey(annotationName)); } @Override - public AnnotationAttributes getAnnotationAttributes(String annotationType) { - return getAnnotationAttributes(annotationType, false); + public AnnotationAttributes getAnnotationAttributes(String annotationName) { + return getAnnotationAttributes(annotationName, false); } @Override - public AnnotationAttributes getAnnotationAttributes(String annotationType, boolean classValuesAsString) { + public AnnotationAttributes getAnnotationAttributes(String annotationName, boolean classValuesAsString) { AnnotationAttributes raw = AnnotationReadingVisitorUtils.getMergedAnnotationAttributes( - this.attributesMap, this.metaAnnotationMap, annotationType); +this.attributesMap, + this.metaAnnotationMap, annotationName); return AnnotationReadingVisitorUtils.convertClassValues(this.classLoader, raw, classValuesAsString); } @Override - public MultiValueMap getAllAnnotationAttributes(String annotationType) { - return getAllAnnotationAttributes(annotationType, false); + public MultiValueMap getAllAnnotationAttributes(String annotationName) { + return getAllAnnotationAttributes(annotationName, false); } @Override - public MultiValueMap getAllAnnotationAttributes(String annotationType, boolean classValuesAsString) { + public MultiValueMap getAllAnnotationAttributes(String annotationName, boolean classValuesAsString) { MultiValueMap allAttributes = new LinkedMultiValueMap(); - List attributes = this.attributesMap.get(annotationType); + List attributes = this.attributesMap.get(annotationName); if (attributes == null) { return null; } @@ -153,9 +154,9 @@ public class AnnotationMetadataReadingVisitor extends ClassMetadataReadingVisito } @Override - public boolean hasAnnotatedMethods(String annotationType) { + public boolean hasAnnotatedMethods(String annotationName) { for (MethodMetadata methodMetadata : this.methodMetadataSet) { - if (methodMetadata.isAnnotated(annotationType)) { + if (methodMetadata.isAnnotated(annotationName)) { return true; } } @@ -163,10 +164,10 @@ public class AnnotationMetadataReadingVisitor extends ClassMetadataReadingVisito } @Override - public Set getAnnotatedMethods(String annotationType) { + public Set getAnnotatedMethods(String annotationName) { Set annotatedMethods = new LinkedHashSet(4); for (MethodMetadata methodMetadata : this.methodMetadataSet) { - if (methodMetadata.isAnnotated(annotationType)) { + if (methodMetadata.isAnnotated(annotationName)) { annotatedMethods.add(methodMetadata); } } diff --git a/spring-core/src/main/java/org/springframework/core/type/classreading/AnnotationReadingVisitorUtils.java b/spring-core/src/main/java/org/springframework/core/type/classreading/AnnotationReadingVisitorUtils.java index 2fe25085e8..aef400633a 100644 --- a/spring-core/src/main/java/org/springframework/core/type/classreading/AnnotationReadingVisitorUtils.java +++ b/spring-core/src/main/java/org/springframework/core/type/classreading/AnnotationReadingVisitorUtils.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2014 the original author or authors. + * Copyright 2002-2015 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -27,9 +27,10 @@ import org.springframework.asm.Type; import org.springframework.core.annotation.AnnotationAttributes; import org.springframework.core.annotation.AnnotationUtils; import org.springframework.util.LinkedMultiValueMap; +import org.springframework.util.ObjectUtils; /** - * Internal utility class used when reading annotations. + * Internal utility class used when reading annotations via ASM. * * @author Juergen Hoeller * @author Mark Fisher @@ -102,21 +103,22 @@ abstract class AnnotationReadingVisitorUtils { *

Annotation attribute values appearing lower in the annotation * hierarchy (i.e., closer to the declaring class) will override those * defined higher in the annotation hierarchy. - * @param attributesMap the map of annotation attribute lists, - * keyed by annotation type name + * @param attributesMap the map of annotation attribute lists, keyed by + * annotation type name * @param metaAnnotationMap the map of meta annotation relationships, * keyed by annotation type name - * @param annotationType the name of the annotation type to look for + * @param annotationName the fully qualified class name of the annotation + * type to look for * @return the merged annotation attributes, or {@code null} if no * matching annotation is present in the {@code attributesMap} * @since 4.0.3 */ public static AnnotationAttributes getMergedAnnotationAttributes( LinkedMultiValueMap attributesMap, - Map> metaAnnotationMap, String annotationType) { + Map> metaAnnotationMap, String annotationName) { // Get the unmerged list of attributes for the target annotation. - List attributesList = attributesMap.get(annotationType); + List attributesList = attributesMap.get(annotationName); if (attributesList == null || attributesList.isEmpty()) { return null; } @@ -137,13 +139,13 @@ abstract class AnnotationReadingVisitorUtils { Collections.reverse(annotationTypes); // No need to revisit the target annotation type: - annotationTypes.remove(annotationType); + annotationTypes.remove(annotationName); for (String currentAnnotationType : annotationTypes) { List currentAttributesList = attributesMap.get(currentAnnotationType); - if (currentAttributesList != null && !currentAttributesList.isEmpty()) { + if (!ObjectUtils.isEmpty(currentAttributesList)) { Set metaAnns = metaAnnotationMap.get(currentAnnotationType); - if (metaAnns != null && metaAnns.contains(annotationType)) { + if (metaAnns != null && metaAnns.contains(annotationName)) { AnnotationAttributes currentAttributes = currentAttributesList.get(0); for (String overridableAttributeName : overridableAttributeNames) { Object value = currentAttributes.get(overridableAttributeName); diff --git a/spring-core/src/main/java/org/springframework/core/type/classreading/MethodMetadataReadingVisitor.java b/spring-core/src/main/java/org/springframework/core/type/classreading/MethodMetadataReadingVisitor.java index 3539c34652..efc1eecdab 100644 --- a/spring-core/src/main/java/org/springframework/core/type/classreading/MethodMetadataReadingVisitor.java +++ b/spring-core/src/main/java/org/springframework/core/type/classreading/MethodMetadataReadingVisitor.java @@ -31,7 +31,7 @@ import org.springframework.util.LinkedMultiValueMap; import org.springframework.util.MultiValueMap; /** - * ASM method visitor which looks for the annotations defined on the method, + * ASM method visitor which looks for the annotations defined on a method, * exposing them through the {@link org.springframework.core.type.MethodMetadata} * interface. * @@ -106,34 +106,34 @@ public class MethodMetadataReadingVisitor extends MethodVisitor implements Metho } @Override - public boolean isAnnotated(String annotationType) { - return this.attributeMap.containsKey(annotationType); + public boolean isAnnotated(String annotationName) { + return this.attributeMap.containsKey(annotationName); } @Override - public Map getAnnotationAttributes(String annotationType) { - return getAnnotationAttributes(annotationType, false); + public Map getAnnotationAttributes(String annotationName) { + return getAnnotationAttributes(annotationName, false); } @Override - public Map getAnnotationAttributes(String annotationType, boolean classValuesAsString) { - List attributes = this.attributeMap.get(annotationType); + public Map getAnnotationAttributes(String annotationName, boolean classValuesAsString) { + List attributes = this.attributeMap.get(annotationName); return (attributes == null ? null : AnnotationReadingVisitorUtils.convertClassValues( this.classLoader, attributes.get(0), classValuesAsString)); } @Override - public MultiValueMap getAllAnnotationAttributes(String annotationType) { - return getAllAnnotationAttributes(annotationType, false); + public MultiValueMap getAllAnnotationAttributes(String annotationName) { + return getAllAnnotationAttributes(annotationName, false); } @Override - public MultiValueMap getAllAnnotationAttributes(String annotationType, boolean classValuesAsString) { - if (!this.attributeMap.containsKey(annotationType)) { + public MultiValueMap getAllAnnotationAttributes(String annotationName, boolean classValuesAsString) { + if (!this.attributeMap.containsKey(annotationName)) { return null; } MultiValueMap allAttributes = new LinkedMultiValueMap(); - for (AnnotationAttributes annotationAttributes : this.attributeMap.get(annotationType)) { + for (AnnotationAttributes annotationAttributes : this.attributeMap.get(annotationName)) { for (Map.Entry entry : AnnotationReadingVisitorUtils.convertClassValues( this.classLoader, annotationAttributes, classValuesAsString).entrySet()) { allAttributes.add(entry.getKey(), entry.getValue()); diff --git a/spring-core/src/test/java/org/springframework/core/annotation/AnnotatedElementUtilsTests.java b/spring-core/src/test/java/org/springframework/core/annotation/AnnotatedElementUtilsTests.java index 96e8546a41..7d7a6c1b0c 100644 --- a/spring-core/src/test/java/org/springframework/core/annotation/AnnotatedElementUtilsTests.java +++ b/spring-core/src/test/java/org/springframework/core/annotation/AnnotatedElementUtilsTests.java @@ -190,10 +190,10 @@ public class AnnotatedElementUtilsTests { } @Test - public void getAnnotationAttributesOnClassWithLocalAnnotation() { + public void getMergedAnnotationAttributesOnClassWithLocalAnnotation() { Class element = TxConfig.class; String name = TX_NAME; - AnnotationAttributes attributes = getAnnotationAttributes(element, name); + AnnotationAttributes attributes = getMergedAnnotationAttributes(element, name); assertNotNull("Annotation attributes for @Transactional on TxConfig", attributes); assertEquals("value for TxConfig.", "TxConfig", attributes.getString("value")); // Verify contracts between utility methods: @@ -201,10 +201,10 @@ public class AnnotatedElementUtilsTests { } @Test - public void getAnnotationAttributesOnClassWithLocalAnnotationThatShadowsAnnotationFromSuperclass() { + public void getMergedAnnotationAttributesOnClassWithLocalAnnotationThatShadowsAnnotationFromSuperclass() { Class element = DerivedTxConfig.class; String name = TX_NAME; - AnnotationAttributes attributes = getAnnotationAttributes(element, name); + AnnotationAttributes attributes = getMergedAnnotationAttributes(element, name); assertNotNull("Annotation attributes for @Transactional on DerivedTxConfig", attributes); assertEquals("value for DerivedTxConfig.", "DerivedTxConfig", attributes.getString("value")); // Verify contracts between utility methods: @@ -212,16 +212,16 @@ public class AnnotatedElementUtilsTests { } @Test - public void getAnnotationAttributesOnMetaCycleAnnotatedClassWithMissingTargetMetaAnnotation() { - AnnotationAttributes attributes = getAnnotationAttributes(MetaCycleAnnotatedClass.class, TX_NAME); + public void getMergedAnnotationAttributesOnMetaCycleAnnotatedClassWithMissingTargetMetaAnnotation() { + AnnotationAttributes attributes = getMergedAnnotationAttributes(MetaCycleAnnotatedClass.class, TX_NAME); assertNull("Should not find annotation attributes for @Transactional on MetaCycleAnnotatedClass", attributes); } @Test - public void getAnnotationAttributesFavorsLocalComposedAnnotationOverInheritedAnnotation() { + public void getMergedAnnotationAttributesFavorsLocalComposedAnnotationOverInheritedAnnotation() { Class element = SubClassWithInheritedAnnotation.class; String name = TX_NAME; - AnnotationAttributes attributes = getAnnotationAttributes(element, name); + AnnotationAttributes attributes = getMergedAnnotationAttributes(element, name); assertNotNull("AnnotationAttributes for @Transactional on SubClassWithInheritedAnnotation", attributes); // Verify contracts between utility methods: assertTrue(isAnnotated(element, name)); @@ -229,10 +229,10 @@ public class AnnotatedElementUtilsTests { } @Test - public void getAnnotationAttributesFavorsInheritedAnnotationsOverMoreLocallyDeclaredComposedAnnotations() { + public void getMergedAnnotationAttributesFavorsInheritedAnnotationsOverMoreLocallyDeclaredComposedAnnotations() { Class element = SubSubClassWithInheritedAnnotation.class; String name = TX_NAME; - AnnotationAttributes attributes = getAnnotationAttributes(element, name); + AnnotationAttributes attributes = getMergedAnnotationAttributes(element, name); assertNotNull("AnnotationAttributes for @Transactional on SubSubClassWithInheritedAnnotation", attributes); // Verify contracts between utility methods: assertTrue(isAnnotated(element, name)); @@ -240,10 +240,10 @@ public class AnnotatedElementUtilsTests { } @Test - public void getAnnotationAttributesFavorsInheritedComposedAnnotationsOverMoreLocallyDeclaredComposedAnnotations() { + public void getMergedAnnotationAttributesFavorsInheritedComposedAnnotationsOverMoreLocallyDeclaredComposedAnnotations() { Class element = SubSubClassWithInheritedComposedAnnotation.class; String name = TX_NAME; - AnnotationAttributes attributes = getAnnotationAttributes(element, name); + AnnotationAttributes attributes = getMergedAnnotationAttributes(element, name); assertNotNull("AnnotationAttributtes for @Transactional on SubSubClassWithInheritedComposedAnnotation.", attributes); // Verify contracts between utility methods: assertTrue(isAnnotated(element, name)); @@ -251,40 +251,40 @@ public class AnnotatedElementUtilsTests { } @Test - public void getAnnotationAttributesFromInterfaceImplementedBySuperclass() { + public void getMergedAnnotationAttributesFromInterfaceImplementedBySuperclass() { Class element = ConcreteClassWithInheritedAnnotation.class; String name = TX_NAME; - AnnotationAttributes attributes = getAnnotationAttributes(element, name); + AnnotationAttributes attributes = getMergedAnnotationAttributes(element, name); assertNull("Should not find @Transactional on ConcreteClassWithInheritedAnnotation", attributes); // Verify contracts between utility methods: assertFalse(isAnnotated(element, name)); } @Test - public void getAnnotationAttributesOnInheritedAnnotationInterface() { + public void getMergedAnnotationAttributesOnInheritedAnnotationInterface() { Class element = InheritedAnnotationInterface.class; String name = TX_NAME; - AnnotationAttributes attributes = getAnnotationAttributes(element, name); + AnnotationAttributes attributes = getMergedAnnotationAttributes(element, name); assertNotNull("Should find @Transactional on InheritedAnnotationInterface", attributes); // Verify contracts between utility methods: assertTrue(isAnnotated(element, name)); } @Test - public void getAnnotationAttributesOnNonInheritedAnnotationInterface() { + public void getMergedAnnotationAttributesOnNonInheritedAnnotationInterface() { Class element = NonInheritedAnnotationInterface.class; String name = Order.class.getName(); - AnnotationAttributes attributes = getAnnotationAttributes(element, name); + AnnotationAttributes attributes = getMergedAnnotationAttributes(element, name); assertNotNull("Should find @Order on NonInheritedAnnotationInterface", attributes); // Verify contracts between utility methods: assertTrue(isAnnotated(element, name)); } @Test - public void getAnnotationAttributesWithConventionBasedComposedAnnotation() { + public void getMergedAnnotationAttributesWithConventionBasedComposedAnnotation() { Class element = ConventionBasedComposedContextConfigClass.class; String name = ContextConfig.class.getName(); - AnnotationAttributes attributes = getAnnotationAttributes(element, name); + AnnotationAttributes attributes = getMergedAnnotationAttributes(element, name); assertNotNull("Should find @ContextConfig on " + element.getSimpleName(), attributes); assertArrayEquals("locations", new String[] { "explicitDeclaration" }, attributes.getStringArray("locations")); @@ -295,10 +295,10 @@ public class AnnotatedElementUtilsTests { } @Test - public void getAnnotationAttributesWithAliasedComposedAnnotation() { + public void getMergedAnnotationAttributesWithAliasedComposedAnnotation() { Class element = AliasedComposedContextConfigClass.class; String name = ContextConfig.class.getName(); - AnnotationAttributes attributes = getAnnotationAttributes(element, name); + AnnotationAttributes attributes = getMergedAnnotationAttributes(element, name); assertNotNull("Should find @ContextConfig on " + element.getSimpleName(), attributes); assertArrayEquals("value", new String[] { "test.xml" }, attributes.getStringArray("value")); @@ -309,10 +309,10 @@ public class AnnotatedElementUtilsTests { } @Test - public void getAnnotationAttributesWithAliasedValueComposedAnnotation() { + public void getMergedAnnotationAttributesWithAliasedValueComposedAnnotation() { Class element = AliasedValueComposedContextConfigClass.class; String name = ContextConfig.class.getName(); - AnnotationAttributes attributes = getAnnotationAttributes(element, name); + AnnotationAttributes attributes = getMergedAnnotationAttributes(element, name); assertNotNull("Should find @ContextConfig on " + element.getSimpleName(), attributes); assertArrayEquals("locations", new String[] { "test.xml" }, attributes.getStringArray("locations")); @@ -323,9 +323,9 @@ public class AnnotatedElementUtilsTests { } @Test - public void getAnnotationWithAliasedValueComposedAnnotation() { + public void getMergeAndSynthesizeAnnotationWithAliasedValueComposedAnnotation() { Class element = AliasedValueComposedContextConfigClass.class; - ContextConfig contextConfig = getAnnotation(element, ContextConfig.class); + ContextConfig contextConfig = getMergedAnnotation(element, ContextConfig.class); assertNotNull("Should find @ContextConfig on " + element.getSimpleName(), contextConfig); assertArrayEquals("locations", new String[] { "test.xml" }, contextConfig.locations()); @@ -336,7 +336,7 @@ public class AnnotatedElementUtilsTests { } @Test - public void getAnnotationAttributesWithInvalidConventionBasedComposedAnnotation() { + public void getMergedAnnotationAttributesWithInvalidConventionBasedComposedAnnotation() { Class element = InvalidConventionBasedComposedContextConfigClass.class; exception.expect(AnnotationConfigurationException.class); exception.expectMessage(either(containsString("attribute [value] and its alias [locations]")).or( @@ -345,11 +345,11 @@ public class AnnotatedElementUtilsTests { containsString("values of [{duplicateDeclaration}] and [{requiredLocationsDeclaration}]")).or( containsString("values of [{requiredLocationsDeclaration}] and [{duplicateDeclaration}]"))); exception.expectMessage(containsString("but only one declaration is permitted")); - getAnnotationAttributes(element, ContextConfig.class); + getMergedAnnotationAttributes(element, ContextConfig.class); } @Test - public void getAnnotationAttributesWithInvalidAliasedComposedAnnotation() { + public void getMergedAnnotationAttributesWithInvalidAliasedComposedAnnotation() { Class element = InvalidAliasedComposedContextConfigClass.class; exception.expect(AnnotationConfigurationException.class); exception.expectMessage(either(containsString("attribute [value] and its alias [locations]")).or( @@ -357,56 +357,56 @@ public class AnnotatedElementUtilsTests { exception.expectMessage(either(containsString("values of [{duplicateDeclaration}] and [{test.xml}]")).or( containsString("values of [{test.xml}] and [{duplicateDeclaration}]"))); exception.expectMessage(containsString("but only one declaration is permitted")); - getAnnotationAttributes(element, ContextConfig.class); + getMergedAnnotationAttributes(element, ContextConfig.class); } @Test - public void findAnnotationAttributesOnInheritedAnnotationInterface() { - AnnotationAttributes attributes = findAnnotationAttributes(InheritedAnnotationInterface.class, Transactional.class); + public void findMergedAnnotationAttributesOnInheritedAnnotationInterface() { + AnnotationAttributes attributes = findMergedAnnotationAttributes(InheritedAnnotationInterface.class, Transactional.class); assertNotNull("Should find @Transactional on InheritedAnnotationInterface", attributes); } @Test - public void findAnnotationAttributesOnSubInheritedAnnotationInterface() { - AnnotationAttributes attributes = findAnnotationAttributes(SubInheritedAnnotationInterface.class, Transactional.class); + public void findMergedAnnotationAttributesOnSubInheritedAnnotationInterface() { + AnnotationAttributes attributes = findMergedAnnotationAttributes(SubInheritedAnnotationInterface.class, Transactional.class); assertNotNull("Should find @Transactional on SubInheritedAnnotationInterface", attributes); } @Test - public void findAnnotationAttributesOnSubSubInheritedAnnotationInterface() { - AnnotationAttributes attributes = findAnnotationAttributes(SubSubInheritedAnnotationInterface.class, Transactional.class); + public void findMergedAnnotationAttributesOnSubSubInheritedAnnotationInterface() { + AnnotationAttributes attributes = findMergedAnnotationAttributes(SubSubInheritedAnnotationInterface.class, Transactional.class); assertNotNull("Should find @Transactional on SubSubInheritedAnnotationInterface", attributes); } @Test - public void findAnnotationAttributesOnNonInheritedAnnotationInterface() { - AnnotationAttributes attributes = findAnnotationAttributes(NonInheritedAnnotationInterface.class, Order.class); + public void findMergedAnnotationAttributesOnNonInheritedAnnotationInterface() { + AnnotationAttributes attributes = findMergedAnnotationAttributes(NonInheritedAnnotationInterface.class, Order.class); assertNotNull("Should find @Order on NonInheritedAnnotationInterface", attributes); } @Test - public void findAnnotationAttributesOnSubNonInheritedAnnotationInterface() { - AnnotationAttributes attributes = findAnnotationAttributes(SubNonInheritedAnnotationInterface.class, Order.class); + public void findMergedAnnotationAttributesOnSubNonInheritedAnnotationInterface() { + AnnotationAttributes attributes = findMergedAnnotationAttributes(SubNonInheritedAnnotationInterface.class, Order.class); assertNotNull("Should find @Order on SubNonInheritedAnnotationInterface", attributes); } @Test - public void findAnnotationAttributesOnSubSubNonInheritedAnnotationInterface() { - AnnotationAttributes attributes = findAnnotationAttributes(SubSubNonInheritedAnnotationInterface.class, Order.class); + public void findMergedAnnotationAttributesOnSubSubNonInheritedAnnotationInterface() { + AnnotationAttributes attributes = findMergedAnnotationAttributes(SubSubNonInheritedAnnotationInterface.class, Order.class); assertNotNull("Should find @Order on SubSubNonInheritedAnnotationInterface", attributes); } @Test - public void findAnnotationAttributesInheritedFromInterfaceMethod() throws NoSuchMethodException { + public void findMergedAnnotationAttributesInheritedFromInterfaceMethod() throws NoSuchMethodException { Method method = ConcreteClassWithInheritedAnnotation.class.getMethod("handleFromInterface"); - AnnotationAttributes attributes = findAnnotationAttributes(method, Order.class); + AnnotationAttributes attributes = findMergedAnnotationAttributes(method, Order.class); assertNotNull("Should find @Order on ConcreteClassWithInheritedAnnotation.handleFromInterface() method", attributes); } @Test - public void findAnnotationAttributesInheritedFromAbstractMethod() throws NoSuchMethodException { + public void findMergedAnnotationAttributesInheritedFromAbstractMethod() throws NoSuchMethodException { Method method = ConcreteClassWithInheritedAnnotation.class.getMethod("handle"); - AnnotationAttributes attributes = findAnnotationAttributes(method, Transactional.class); + AnnotationAttributes attributes = findMergedAnnotationAttributes(method, Transactional.class); assertNotNull("Should find @Transactional on ConcreteClassWithInheritedAnnotation.handle() method", attributes); } @@ -421,9 +421,9 @@ public class AnnotatedElementUtilsTests { * @since 4.2 */ @Test - public void findAnnotationAttributesInheritedFromBridgedMethod() throws NoSuchMethodException { + public void findMergedAnnotationAttributesInheritedFromBridgedMethod() throws NoSuchMethodException { Method method = ConcreteClassWithInheritedAnnotation.class.getMethod("handleParameterized", String.class); - AnnotationAttributes attributes = findAnnotationAttributes(method, Transactional.class); + AnnotationAttributes attributes = findMergedAnnotationAttributes(method, Transactional.class); assertNull("Should not find @Transactional on bridged ConcreteClassWithInheritedAnnotation.handleParameterized()", attributes); } @@ -433,7 +433,7 @@ public class AnnotatedElementUtilsTests { * @since 4.2 */ @Test - public void findAnnotationAttributesFromBridgeMethod() throws NoSuchMethodException { + public void findMergedAnnotationAttributesFromBridgeMethod() throws NoSuchMethodException { Method[] methods = StringGenericParameter.class.getMethods(); Method bridgeMethod = null; Method bridgedMethod = null; @@ -450,13 +450,13 @@ public class AnnotatedElementUtilsTests { assertTrue(bridgeMethod != null && bridgeMethod.isBridge()); assertTrue(bridgedMethod != null && !bridgedMethod.isBridge()); - AnnotationAttributes attributes = findAnnotationAttributes(bridgeMethod, Order.class); + AnnotationAttributes attributes = findMergedAnnotationAttributes(bridgeMethod, Order.class); assertNotNull("Should find @Order on StringGenericParameter.getFor() bridge method", attributes); } @Test - public void findAnnotationAttributesOnClassWithMetaAndLocalTxConfig() { - AnnotationAttributes attributes = findAnnotationAttributes(MetaAndLocalTxConfigClass.class, Transactional.class); + public void findMergedAnnotationAttributesOnClassWithMetaAndLocalTxConfig() { + AnnotationAttributes attributes = findMergedAnnotationAttributes(MetaAndLocalTxConfigClass.class, Transactional.class); assertNotNull("Should find @Transactional on MetaAndLocalTxConfigClass", attributes); assertEquals("TX qualifier for MetaAndLocalTxConfigClass.", "localTxMgr", attributes.getString("qualifier")); } @@ -466,7 +466,7 @@ public class AnnotatedElementUtilsTests { String qualifier = "aliasForQualifier"; // 1) Find and merge AnnotationAttributes from the annotation hierarchy - AnnotationAttributes attributes = findAnnotationAttributes(AliasedTransactionalComponentClass.class, + AnnotationAttributes attributes = findMergedAnnotationAttributes(AliasedTransactionalComponentClass.class, AliasedTransactional.class); assertNotNull("@AliasedTransactional on AliasedTransactionalComponentClass.", attributes); @@ -483,18 +483,18 @@ public class AnnotatedElementUtilsTests { } @Test - public void findAnnotationWithAttributeAliasesInTargetAnnotation() { + public void findMergedAnnotationWithAttributeAliasesInTargetAnnotation() { Class element = AliasedTransactionalComponentClass.class; - AliasedTransactional annotation = findAnnotation(element, AliasedTransactional.class); + AliasedTransactional annotation = findMergedAnnotation(element, AliasedTransactional.class); assertNotNull("@AliasedTransactional on " + element, annotation); assertEquals("TX value via synthesized annotation.", "aliasForQualifier", annotation.value()); assertEquals("TX qualifier via synthesized annotation.", "aliasForQualifier", annotation.qualifier()); } @Test - public void findAnnotationAttributesOnClassWithAttributeAliasInComposedAnnotationAndNestedAnnotationsInTargetAnnotation() { + public void findMergedAnnotationAttributesOnClassWithAttributeAliasInComposedAnnotationAndNestedAnnotationsInTargetAnnotation() { Class element = TestComponentScanClass.class; - AnnotationAttributes attributes = findAnnotationAttributes(element, ComponentScan.class); + AnnotationAttributes attributes = findMergedAnnotationAttributes(element, ComponentScan.class); assertNotNull("Should find @ComponentScan on " + element, attributes); assertArrayEquals("basePackages for " + element, new String[] { "com.example.app.test" }, attributes.getStringArray("basePackages")); @@ -511,9 +511,9 @@ public class AnnotatedElementUtilsTests { } - static AnnotationAttributes findAnnotationAttributes(AnnotatedElement element, Class annotationType) { + static AnnotationAttributes findMergedAnnotationAttributes(AnnotatedElement element, Class annotationType) { Assert.notNull(annotationType, "annotationType must not be null"); - return AnnotatedElementUtils.findAnnotationAttributes(element, annotationType.getName(), false, false); + return AnnotatedElementUtils.findMergedAnnotationAttributes(element, annotationType.getName(), false, false); } diff --git a/spring-test/src/main/java/org/springframework/test/annotation/TestAnnotationUtils.java b/spring-test/src/main/java/org/springframework/test/annotation/TestAnnotationUtils.java index ec28fbf230..5f4eb1c247 100644 --- a/spring-test/src/main/java/org/springframework/test/annotation/TestAnnotationUtils.java +++ b/spring-test/src/main/java/org/springframework/test/annotation/TestAnnotationUtils.java @@ -37,7 +37,7 @@ public class TestAnnotationUtils { * annotated with {@code @Timed} */ public static long getTimeout(Method method) { - Timed timed = AnnotatedElementUtils.findAnnotation(method, Timed.class); + Timed timed = AnnotatedElementUtils.findMergedAnnotation(method, Timed.class); if (timed == null) { return 0; } diff --git a/spring-test/src/main/java/org/springframework/test/context/jdbc/MergedSqlConfig.java b/spring-test/src/main/java/org/springframework/test/context/jdbc/MergedSqlConfig.java index 0a2a11f77a..63dc1c1b71 100644 --- a/spring-test/src/main/java/org/springframework/test/context/jdbc/MergedSqlConfig.java +++ b/spring-test/src/main/java/org/springframework/test/context/jdbc/MergedSqlConfig.java @@ -86,7 +86,7 @@ class MergedSqlConfig { Assert.notNull(testClass, "testClass must not be null"); // Get global attributes, if any. - AnnotationAttributes attributes = AnnotatedElementUtils.findAnnotationAttributes(testClass, + AnnotationAttributes attributes = AnnotatedElementUtils.findMergedAnnotationAttributes(testClass, SqlConfig.class.getName(), false, false); // Override global attributes with local attributes. diff --git a/spring-test/src/main/java/org/springframework/test/context/support/AbstractTestContextBootstrapper.java b/spring-test/src/main/java/org/springframework/test/context/support/AbstractTestContextBootstrapper.java index 1f44ce1e62..e03b89625b 100644 --- a/spring-test/src/main/java/org/springframework/test/context/support/AbstractTestContextBootstrapper.java +++ b/spring-test/src/main/java/org/springframework/test/context/support/AbstractTestContextBootstrapper.java @@ -137,7 +137,7 @@ public abstract class AbstractTestContextBootstrapper implements TestContextBoot // Traverse the class hierarchy... while (descriptor != null) { Class declaringClass = descriptor.getDeclaringClass(); - TestExecutionListeners testExecutionListeners = descriptor.getMergedAnnotation(); + TestExecutionListeners testExecutionListeners = descriptor.synthesizeAnnotation(); if (logger.isTraceEnabled()) { logger.trace(String.format("Retrieved @TestExecutionListeners [%s] for declaring class [%s].", testExecutionListeners, declaringClass.getName())); diff --git a/spring-test/src/main/java/org/springframework/test/context/support/ActiveProfilesUtils.java b/spring-test/src/main/java/org/springframework/test/context/support/ActiveProfilesUtils.java index f542eac4ab..15a281a4de 100644 --- a/spring-test/src/main/java/org/springframework/test/context/support/ActiveProfilesUtils.java +++ b/spring-test/src/main/java/org/springframework/test/context/support/ActiveProfilesUtils.java @@ -86,7 +86,7 @@ abstract class ActiveProfilesUtils { while (descriptor != null) { Class rootDeclaringClass = descriptor.getRootDeclaringClass(); Class declaringClass = descriptor.getDeclaringClass(); - ActiveProfiles annotation = descriptor.getMergedAnnotation(); + ActiveProfiles annotation = descriptor.synthesizeAnnotation(); if (logger.isTraceEnabled()) { logger.trace(String.format("Retrieved @ActiveProfiles [%s] for declaring class [%s].", annotation, diff --git a/spring-test/src/main/java/org/springframework/test/context/support/ContextLoaderUtils.java b/spring-test/src/main/java/org/springframework/test/context/support/ContextLoaderUtils.java index 78877b64eb..d86585d733 100644 --- a/spring-test/src/main/java/org/springframework/test/context/support/ContextLoaderUtils.java +++ b/spring-test/src/main/java/org/springframework/test/context/support/ContextLoaderUtils.java @@ -26,6 +26,7 @@ import java.util.Set; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import org.springframework.core.annotation.AnnotationUtils; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.ContextConfigurationAttributes; import org.springframework.test.context.ContextHierarchy; @@ -132,8 +133,10 @@ abstract class ContextLoaderUtils { final List configAttributesList = new ArrayList(); if (contextConfigDeclaredLocally) { - convertContextConfigToConfigAttributesAndAddToList( - (ContextConfiguration) descriptor.getMergedAnnotation(), rootDeclaringClass, + ContextConfiguration contextConfiguration = AnnotationUtils.synthesizeAnnotation( + descriptor.getAnnotationAttributes(), ContextConfiguration.class, + descriptor.getRootDeclaringClass()); + convertContextConfigToConfigAttributesAndAddToList(contextConfiguration, rootDeclaringClass, configAttributesList); } else if (contextHierarchyDeclaredLocally) { @@ -256,7 +259,7 @@ abstract class ContextLoaderUtils { annotationType.getName(), testClass.getName())); while (descriptor != null) { - convertContextConfigToConfigAttributesAndAddToList(descriptor.getMergedAnnotation(), + convertContextConfigToConfigAttributesAndAddToList(descriptor.synthesizeAnnotation(), descriptor.getRootDeclaringClass(), attributesList); descriptor = findAnnotationDescriptor(descriptor.getRootDeclaringClass().getSuperclass(), annotationType); } diff --git a/spring-test/src/main/java/org/springframework/test/context/support/DefaultActiveProfilesResolver.java b/spring-test/src/main/java/org/springframework/test/context/support/DefaultActiveProfilesResolver.java index a48f32fc71..d03f0f1c1a 100644 --- a/spring-test/src/main/java/org/springframework/test/context/support/DefaultActiveProfilesResolver.java +++ b/spring-test/src/main/java/org/springframework/test/context/support/DefaultActiveProfilesResolver.java @@ -73,7 +73,7 @@ public class DefaultActiveProfilesResolver implements ActiveProfilesResolver { } else { Class declaringClass = descriptor.getDeclaringClass(); - ActiveProfiles annotation = descriptor.getMergedAnnotation(); + ActiveProfiles annotation = descriptor.synthesizeAnnotation(); if (logger.isTraceEnabled()) { logger.trace(String.format("Retrieved @ActiveProfiles [%s] for declaring class [%s].", annotation, diff --git a/spring-test/src/main/java/org/springframework/test/context/support/DirtiesContextTestExecutionListener.java b/spring-test/src/main/java/org/springframework/test/context/support/DirtiesContextTestExecutionListener.java index bde9b0f45a..67f851f620 100644 --- a/spring-test/src/main/java/org/springframework/test/context/support/DirtiesContextTestExecutionListener.java +++ b/spring-test/src/main/java/org/springframework/test/context/support/DirtiesContextTestExecutionListener.java @@ -155,8 +155,8 @@ public class DirtiesContextTestExecutionListener extends AbstractTestExecutionLi Assert.notNull(testClass, "The test class of the supplied TestContext must not be null"); Assert.notNull(testMethod, "The test method of the supplied TestContext must not be null"); - DirtiesContext methodAnn = AnnotatedElementUtils.findAnnotation(testMethod, DirtiesContext.class); - DirtiesContext classAnn = AnnotatedElementUtils.findAnnotation(testClass, DirtiesContext.class); + DirtiesContext methodAnn = AnnotatedElementUtils.findMergedAnnotation(testMethod, DirtiesContext.class); + DirtiesContext classAnn = AnnotatedElementUtils.findMergedAnnotation(testClass, DirtiesContext.class); boolean methodAnnotated = (methodAnn != null); boolean classAnnotated = (classAnn != null); MethodMode methodMode = (methodAnnotated ? methodAnn.methodMode() : null); @@ -183,7 +183,7 @@ public class DirtiesContextTestExecutionListener extends AbstractTestExecutionLi Class testClass = testContext.getTestClass(); Assert.notNull(testClass, "The test class of the supplied TestContext must not be null"); - DirtiesContext dirtiesContext = AnnotatedElementUtils.findAnnotation(testClass, DirtiesContext.class); + DirtiesContext dirtiesContext = AnnotatedElementUtils.findMergedAnnotation(testClass, DirtiesContext.class); boolean classAnnotated = (dirtiesContext != null); ClassMode classMode = (classAnnotated ? dirtiesContext.classMode() : null); diff --git a/spring-test/src/main/java/org/springframework/test/context/support/TestPropertySourceUtils.java b/spring-test/src/main/java/org/springframework/test/context/support/TestPropertySourceUtils.java index 4b0994ebd7..1619ea8458 100644 --- a/spring-test/src/main/java/org/springframework/test/context/support/TestPropertySourceUtils.java +++ b/spring-test/src/main/java/org/springframework/test/context/support/TestPropertySourceUtils.java @@ -96,7 +96,7 @@ public abstract class TestPropertySourceUtils { annotationType.getName(), testClass.getName())); while (descriptor != null) { - TestPropertySource testPropertySource = descriptor.getMergedAnnotation(); + TestPropertySource testPropertySource = descriptor.synthesizeAnnotation(); Class rootDeclaringClass = descriptor.getRootDeclaringClass(); if (logger.isTraceEnabled()) { diff --git a/spring-test/src/main/java/org/springframework/test/context/transaction/TransactionalTestExecutionListener.java b/spring-test/src/main/java/org/springframework/test/context/transaction/TransactionalTestExecutionListener.java index 49fa5c3903..60d81664d4 100644 --- a/spring-test/src/main/java/org/springframework/test/context/transaction/TransactionalTestExecutionListener.java +++ b/spring-test/src/main/java/org/springframework/test/context/transaction/TransactionalTestExecutionListener.java @@ -499,7 +499,7 @@ public class TransactionalTestExecutionListener extends AbstractTestExecutionLis if (this.configurationAttributes == null) { Class clazz = testContext.getTestClass(); - TransactionConfiguration txConfig = AnnotatedElementUtils.findAnnotation(clazz, + TransactionConfiguration txConfig = AnnotatedElementUtils.findMergedAnnotation(clazz, TransactionConfiguration.class); if (logger.isDebugEnabled()) { logger.debug(String.format("Retrieved @TransactionConfiguration [%s] for test class [%s].", diff --git a/spring-test/src/main/java/org/springframework/test/util/MetaAnnotationUtils.java b/spring-test/src/main/java/org/springframework/test/util/MetaAnnotationUtils.java index 525e0999e4..2503a998de 100644 --- a/spring-test/src/main/java/org/springframework/test/util/MetaAnnotationUtils.java +++ b/spring-test/src/main/java/org/springframework/test/util/MetaAnnotationUtils.java @@ -272,8 +272,6 @@ public abstract class MetaAnnotationUtils { private final T annotation; - private final T mergedAnnotation; - private final AnnotationAttributes annotationAttributes; @@ -281,7 +279,6 @@ public abstract class MetaAnnotationUtils { this(rootDeclaringClass, rootDeclaringClass, null, annotation); } - @SuppressWarnings("unchecked") public AnnotationDescriptor(Class rootDeclaringClass, Class declaringClass, Annotation composedAnnotation, T annotation) { Assert.notNull(rootDeclaringClass, "rootDeclaringClass must not be null"); @@ -290,10 +287,8 @@ public abstract class MetaAnnotationUtils { this.declaringClass = declaringClass; this.composedAnnotation = composedAnnotation; this.annotation = annotation; - this.annotationAttributes = AnnotatedElementUtils.findAnnotationAttributes(rootDeclaringClass, + this.annotationAttributes = AnnotatedElementUtils.findMergedAnnotationAttributes(rootDeclaringClass, annotation.annotationType().getName(), false, false); - this.mergedAnnotation = AnnotationUtils.synthesizeAnnotation(annotationAttributes, - (Class) annotation.annotationType(), rootDeclaringClass); } public Class getRootDeclaringClass() { @@ -309,13 +304,18 @@ public abstract class MetaAnnotationUtils { } /** - * Get the annotation that was synthesized from the merged - * {@link #getAnnotationAttributes AnnotationAttributes}. + * Synthesize the merged {@link #getAnnotationAttributes AnnotationAttributes} + * in this descriptor back into an annotation of the target + * {@linkplain #getAnnotationType annotation type}. + * @since 4.2 * @see #getAnnotationAttributes() + * @see #getAnnotationType() * @see AnnotationUtils#synthesizeAnnotation(java.util.Map, Class, java.lang.reflect.AnnotatedElement) */ - public T getMergedAnnotation() { - return this.mergedAnnotation; + @SuppressWarnings("unchecked") + public T synthesizeAnnotation() { + return AnnotationUtils.synthesizeAnnotation(getAnnotationAttributes(), (Class) getAnnotationType(), + getRootDeclaringClass()); } public Class getAnnotationType() { @@ -364,6 +364,18 @@ public abstract class MetaAnnotationUtils { Annotation composedAnnotation, Annotation annotation) { super(rootDeclaringClass, declaringClass, composedAnnotation, annotation); } + + /** + * Throws an {@link UnsupportedOperationException} since the type of annotation + * represented by the {@link #getAnnotationAttributes AnnotationAttributes} in + * an {@code UntypedAnnotationDescriptor} is unknown. + * @since 4.2 + */ + @Override + public Annotation synthesizeAnnotation() { + throw new UnsupportedOperationException( + "getMergedAnnotation() is unsupported in UntypedAnnotationDescriptor"); + } } } diff --git a/spring-tx/src/main/java/org/springframework/transaction/annotation/JtaTransactionAnnotationParser.java b/spring-tx/src/main/java/org/springframework/transaction/annotation/JtaTransactionAnnotationParser.java index e8c76af63d..dcecefb54c 100644 --- a/spring-tx/src/main/java/org/springframework/transaction/annotation/JtaTransactionAnnotationParser.java +++ b/spring-tx/src/main/java/org/springframework/transaction/annotation/JtaTransactionAnnotationParser.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2013 the original author or authors. + * Copyright 2002-2015 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -39,7 +39,7 @@ public class JtaTransactionAnnotationParser implements TransactionAnnotationPars @Override public TransactionAttribute parseTransactionAnnotation(AnnotatedElement ae) { - AnnotationAttributes attributes = AnnotatedElementUtils.getAnnotationAttributes(ae, javax.transaction.Transactional.class); + AnnotationAttributes attributes = AnnotatedElementUtils.getMergedAnnotationAttributes(ae, javax.transaction.Transactional.class); if (attributes != null) { return parseTransactionAnnotation(attributes); } diff --git a/spring-tx/src/main/java/org/springframework/transaction/annotation/SpringTransactionAnnotationParser.java b/spring-tx/src/main/java/org/springframework/transaction/annotation/SpringTransactionAnnotationParser.java index c6eda30573..df9a310946 100644 --- a/spring-tx/src/main/java/org/springframework/transaction/annotation/SpringTransactionAnnotationParser.java +++ b/spring-tx/src/main/java/org/springframework/transaction/annotation/SpringTransactionAnnotationParser.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2013 the original author or authors. + * Copyright 2002-2015 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -39,7 +39,7 @@ public class SpringTransactionAnnotationParser implements TransactionAnnotationP @Override public TransactionAttribute parseTransactionAnnotation(AnnotatedElement ae) { - AnnotationAttributes attributes = AnnotatedElementUtils.getAnnotationAttributes(ae, Transactional.class); + AnnotationAttributes attributes = AnnotatedElementUtils.getMergedAnnotationAttributes(ae, Transactional.class); if (attributes != null) { return parseTransactionAnnotation(attributes); } diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/MvcUriComponentsBuilder.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/MvcUriComponentsBuilder.java index ba9858004f..73b1abcbed 100644 --- a/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/MvcUriComponentsBuilder.java +++ b/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/MvcUriComponentsBuilder.java @@ -418,7 +418,7 @@ public class MvcUriComponentsBuilder { private static String getTypeRequestMapping(Class controllerType) { Assert.notNull(controllerType, "'controllerType' must not be null"); - RequestMapping requestMapping = AnnotatedElementUtils.findAnnotation(controllerType, RequestMapping.class); + RequestMapping requestMapping = AnnotatedElementUtils.findMergedAnnotation(controllerType, RequestMapping.class); if (requestMapping == null) { return "/"; } @@ -433,7 +433,8 @@ public class MvcUriComponentsBuilder { } private static String getMethodRequestMapping(Method method) { - RequestMapping requestMapping = AnnotatedElementUtils.findAnnotation(method, RequestMapping.class); + Assert.notNull(method, "'method' must not be null"); + RequestMapping requestMapping = AnnotatedElementUtils.findMergedAnnotation(method, RequestMapping.class); if (requestMapping == null) { throw new IllegalArgumentException("No @RequestMapping on: " + method.toGenericString()); } diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/RequestMappingHandlerMapping.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/RequestMappingHandlerMapping.java index 706e86796d..156ba34a82 100644 --- a/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/RequestMappingHandlerMapping.java +++ b/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/RequestMappingHandlerMapping.java @@ -209,7 +209,7 @@ public class RequestMappingHandlerMapping extends RequestMappingInfoHandlerMappi * @see #getCustomMethodCondition(Method) */ private RequestMappingInfo createRequestMappingInfo(AnnotatedElement element) { - RequestMapping requestMapping = AnnotatedElementUtils.findAnnotation(element, RequestMapping.class); + RequestMapping requestMapping = AnnotatedElementUtils.findMergedAnnotation(element, RequestMapping.class); RequestCondition condition = (element instanceof Class ? getCustomTypeCondition((Class) element) : getCustomMethodCondition((Method) element));