From 32c17bf54021440d629fffb1389d3a586bfb42e3 Mon Sep 17 00:00:00 2001 From: Sam Brannen Date: Sun, 14 Jun 2015 00:21:15 +0200 Subject: [PATCH] Revise method and parameter names in annotation support In AnnotatedElementUtils, all methods pertaining to merging annotation attributes have been renamed to "getMerged*()" and "findMerged*()" accordingly. Existing methods such as getAnnotationAttributes(..) have been deprecated in favor of the more descriptive "merged" variants. This aligns the naming conventions in AnnotatedElementUtils with those already present in AnnotationReadingVisitorUtils. The use of "annotationType" as a variable name for the fully qualified class name of an annotation type has been replaced with "annotationName" in order to improve the readability and intent of the code base. In MetaAnnotationUtils.AnnotationDescriptor, getMergedAnnotation() has been renamed to synthesizeAnnotation(), and the method is now overridden in UntypedAnnotationDescriptor to always throw an UnsupportedOperationException in order to avoid potential run-time ClassCastExceptions. Issue: SPR-11511 --- .../AutowiredAnnotationBeanPostProcessor.java | 2 +- .../ApplicationListenerMethodAdapter.java | 2 +- .../annotation/AnnotatedElementUtils.java | 290 ++++++++++-------- .../core/annotation/AnnotationUtils.java | 28 +- .../core/type/AnnotatedTypeMetadata.java | 27 +- .../core/type/AnnotationMetadata.java | 38 ++- .../core/type/StandardAnnotationMetadata.java | 45 +-- .../core/type/StandardMethodMetadata.java | 23 +- .../AnnotationMetadataReadingVisitor.java | 37 +-- .../AnnotationReadingVisitorUtils.java | 22 +- .../MethodMetadataReadingVisitor.java | 24 +- .../AnnotatedElementUtilsTests.java | 118 +++---- .../test/annotation/TestAnnotationUtils.java | 2 +- .../test/context/jdbc/MergedSqlConfig.java | 2 +- .../AbstractTestContextBootstrapper.java | 2 +- .../context/support/ActiveProfilesUtils.java | 2 +- .../context/support/ContextLoaderUtils.java | 9 +- .../DefaultActiveProfilesResolver.java | 2 +- .../DirtiesContextTestExecutionListener.java | 6 +- .../support/TestPropertySourceUtils.java | 2 +- .../TransactionalTestExecutionListener.java | 2 +- .../test/util/MetaAnnotationUtils.java | 32 +- .../JtaTransactionAnnotationParser.java | 4 +- .../SpringTransactionAnnotationParser.java | 4 +- .../annotation/MvcUriComponentsBuilder.java | 5 +- .../RequestMappingHandlerMapping.java | 2 +- 26 files changed, 390 insertions(+), 342 deletions(-) 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));