Browse Source

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
pull/1430/head
Sam Brannen 10 years ago
parent
commit
32c17bf540
  1. 2
      spring-beans/src/main/java/org/springframework/beans/factory/annotation/AutowiredAnnotationBeanPostProcessor.java
  2. 2
      spring-context/src/main/java/org/springframework/context/event/ApplicationListenerMethodAdapter.java
  3. 290
      spring-core/src/main/java/org/springframework/core/annotation/AnnotatedElementUtils.java
  4. 28
      spring-core/src/main/java/org/springframework/core/annotation/AnnotationUtils.java
  5. 27
      spring-core/src/main/java/org/springframework/core/type/AnnotatedTypeMetadata.java
  6. 38
      spring-core/src/main/java/org/springframework/core/type/AnnotationMetadata.java
  7. 45
      spring-core/src/main/java/org/springframework/core/type/StandardAnnotationMetadata.java
  8. 23
      spring-core/src/main/java/org/springframework/core/type/StandardMethodMetadata.java
  9. 37
      spring-core/src/main/java/org/springframework/core/type/classreading/AnnotationMetadataReadingVisitor.java
  10. 22
      spring-core/src/main/java/org/springframework/core/type/classreading/AnnotationReadingVisitorUtils.java
  11. 24
      spring-core/src/main/java/org/springframework/core/type/classreading/MethodMetadataReadingVisitor.java
  12. 118
      spring-core/src/test/java/org/springframework/core/annotation/AnnotatedElementUtilsTests.java
  13. 2
      spring-test/src/main/java/org/springframework/test/annotation/TestAnnotationUtils.java
  14. 2
      spring-test/src/main/java/org/springframework/test/context/jdbc/MergedSqlConfig.java
  15. 2
      spring-test/src/main/java/org/springframework/test/context/support/AbstractTestContextBootstrapper.java
  16. 2
      spring-test/src/main/java/org/springframework/test/context/support/ActiveProfilesUtils.java
  17. 9
      spring-test/src/main/java/org/springframework/test/context/support/ContextLoaderUtils.java
  18. 2
      spring-test/src/main/java/org/springframework/test/context/support/DefaultActiveProfilesResolver.java
  19. 6
      spring-test/src/main/java/org/springframework/test/context/support/DirtiesContextTestExecutionListener.java
  20. 2
      spring-test/src/main/java/org/springframework/test/context/support/TestPropertySourceUtils.java
  21. 2
      spring-test/src/main/java/org/springframework/test/context/transaction/TransactionalTestExecutionListener.java
  22. 32
      spring-test/src/main/java/org/springframework/test/util/MetaAnnotationUtils.java
  23. 4
      spring-tx/src/main/java/org/springframework/transaction/annotation/JtaTransactionAnnotationParser.java
  24. 4
      spring-tx/src/main/java/org/springframework/transaction/annotation/SpringTransactionAnnotationParser.java
  25. 5
      spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/MvcUriComponentsBuilder.java
  26. 2
      spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/RequestMappingHandlerMapping.java

2
spring-beans/src/main/java/org/springframework/beans/factory/annotation/AutowiredAnnotationBeanPostProcessor.java

@ -442,7 +442,7 @@ public class AutowiredAnnotationBeanPostProcessor extends InstantiationAwareBean @@ -442,7 +442,7 @@ public class AutowiredAnnotationBeanPostProcessor extends InstantiationAwareBean
private AnnotationAttributes findAutowiredAnnotation(AccessibleObject ao) {
for (Class<? extends Annotation> type : this.autowiredAnnotationTypes) {
AnnotationAttributes attributes = AnnotatedElementUtils.getAnnotationAttributes(ao, type);
AnnotationAttributes attributes = AnnotatedElementUtils.getMergedAnnotationAttributes(ao, type);
if (attributes != null) {
return attributes;
}

2
spring-context/src/main/java/org/springframework/context/event/ApplicationListenerMethodAdapter.java

@ -248,7 +248,7 @@ public class ApplicationListenerMethodAdapter implements GenericApplicationListe @@ -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();
}

290
spring-core/src/main/java/org/springframework/core/annotation/AnnotatedElementUtils.java

@ -48,8 +48,9 @@ import org.springframework.util.StringUtils; @@ -48,8 +48,9 @@ import org.springframework.util.StringUtils;
* <h3>Annotation Attribute Overrides</h3>
* <p>Support for meta-annotations with <em>attribute overrides</em> in
* <em>composed annotations</em> 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.
*
* <h3>Find vs. Get Semantics</h3>
* <p>The search algorithms used by methods in this class follow either
@ -59,7 +60,7 @@ import org.springframework.util.StringUtils; @@ -59,7 +60,7 @@ import org.springframework.util.StringUtils;
* <p><strong>Get semantics</strong> are limited to searching for annotations
* that are either <em>present</em> on an {@code AnnotatedElement} (i.e.,
* declared locally or {@linkplain java.lang.annotation.Inherited inherited})
* or declared within the annotation hierarchy <em>above</em> an
* or declared within the annotation hierarchy <em>above</em> the
* {@code AnnotatedElement}.
*
* <p><strong>Find semantics</strong> are much more exhaustive, providing
@ -110,11 +111,11 @@ public class AnnotatedElementUtils { @@ -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<String> getMetaAnnotationTypes(AnnotatedElement element,
Class<? extends Annotation> annotationType) {
public static Set<String> getMetaAnnotationTypes(AnnotatedElement element, Class<? extends Annotation> annotationType) {
Assert.notNull(annotationType, "annotationType must not be null");
return getMetaAnnotationTypes(element, annotationType.getName());
}
@ -122,29 +123,29 @@ public class AnnotatedElementUtils { @@ -122,29 +123,29 @@ public class AnnotatedElementUtils {
/**
* Get the fully qualified class names of all meta-annotation
* types <em>present</em> on the annotation (of the specified
* {@code annotationType}) on the supplied {@link AnnotatedElement}.
* {@code annotationName}) on the supplied {@link AnnotatedElement}.
*
* <p>This method follows <em>get semantics</em> 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<String> getMetaAnnotationTypes(AnnotatedElement element, String annotationType) {
public static Set<String> 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<String> types = new LinkedHashSet<String>();
try {
Annotation annotation = getAnnotation(element, annotationType);
Annotation annotation = getAnnotation(element, annotationName);
if (annotation != null) {
searchWithGetSemantics(annotation.annotationType(), annotationType, new SimpleAnnotationProcessor<Object>() {
searchWithGetSemantics(annotation.annotationType(), annotationName, new SimpleAnnotationProcessor<Object>() {
@Override
public Object process(AnnotatedElement annotatedElement, Annotation annotation, int metaDepth) {
@ -165,54 +166,54 @@ public class AnnotatedElementUtils { @@ -165,54 +166,54 @@ public class AnnotatedElementUtils {
/**
* Determine if the supplied {@link AnnotatedElement} is annotated with
* a <em>composed annotation</em> that is meta-annotated with an
* annotation of the specified {@code annotationType}.
* annotation of the specified {@code annotationName}.
*
* <p>This method follows <em>get semantics</em> 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<Boolean>() {
return Boolean.TRUE.equals(searchWithGetSemantics(element, annotationName, new SimpleAnnotationProcessor<Boolean>() {
@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 <em>present</em> on the supplied {@link AnnotatedElement} or
* within the annotation hierarchy <em>above</em> the specified element.
*
* <p>If this method returns {@code true}, then {@link #getAnnotationAttributes}
* <p>If this method returns {@code true}, then {@link #getMergedAnnotationAttributes}
* will return a non-null value.
*
* <p>This method follows <em>get semantics</em> 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<Boolean>() {
return Boolean.TRUE.equals(searchWithGetSemantics(element, annotationName, new SimpleAnnotationProcessor<Boolean>() {
@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 { @@ -228,19 +229,19 @@ public class AnnotatedElementUtils {
* <p>{@link AliasFor @AliasFor} semantics are fully supported, both
* within a single annotation and within the annotation hierarchy.
*
* <p>This method delegates to {@link #getAnnotationAttributes(AnnotatedElement, Class)}
* <p>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 extends Annotation> A getAnnotation(AnnotatedElement element, Class<A> annotationType) {
AnnotationAttributes attributes = getAnnotationAttributes(element, annotationType);
public static <A extends Annotation> A getMergedAnnotation(AnnotatedElement element, Class<A> annotationType) {
AnnotationAttributes attributes = getMergedAnnotationAttributes(element, annotationType);
return ((attributes != null) ? AnnotationUtils.synthesizeAnnotation(attributes, annotationType, element) : null);
}
@ -253,25 +254,32 @@ public class AnnotatedElementUtils { @@ -253,25 +254,32 @@ public class AnnotatedElementUtils {
* <p>{@link AliasFor @AliasFor} semantics are fully supported, both
* within a single annotation and within the annotation hierarchy.
*
* <p>This method delegates to {@link #getAnnotationAttributes(AnnotatedElement, String)}.
* <p>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<? extends Annotation> annotationType) {
public static AnnotationAttributes getMergedAnnotationAttributes(AnnotatedElement element, Class<? extends Annotation> 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 <em>above</em> the supplied {@code element} and
* merge that annotation's attributes with <em>matching</em> attributes from
* annotations in lower levels of the annotation hierarchy.
@ -279,25 +287,35 @@ public class AnnotatedElementUtils { @@ -279,25 +287,35 @@ public class AnnotatedElementUtils {
* <p>{@link AliasFor @AliasFor} semantics are fully supported, both
* within a single annotation and within the annotation hierarchy.
*
* <p>This method delegates to {@link #getAnnotationAttributes(AnnotatedElement, String, boolean, boolean)},
* <p>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 <em>above</em> the supplied {@code element} and
* merge that annotation's attributes with <em>matching</em> attributes from
* annotations in lower levels of the annotation hierarchy.
@ -310,14 +328,14 @@ public class AnnotatedElementUtils { @@ -310,14 +328,14 @@ public class AnnotatedElementUtils {
* <p>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.
*
* <p>This method follows <em>get semantics</em> 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 { @@ -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 { @@ -350,53 +369,53 @@ public class AnnotatedElementUtils {
* <p>{@link AliasFor @AliasFor} semantics are fully supported, both
* within a single annotation and within the annotation hierarchy.
*
* <p>This method delegates to {@link #findAnnotation(AnnotatedElement, String)}.
* <p>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 extends Annotation> A findAnnotation(AnnotatedElement element, Class<A> annotationType) {
public static <A extends Annotation> A findMergedAnnotation(AnnotatedElement element, Class<A> 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 <em>above</em> the supplied {@code element},
* merge that annotation's attributes with <em>matching</em> 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}.
*
* <p>{@link AliasFor @AliasFor} semantics are fully supported, both
* within a single annotation and within the annotation hierarchy.
*
* <p>This method delegates to {@link #findAnnotationAttributes(AnnotatedElement, String, boolean, boolean)}
* <p>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 extends Annotation> A findAnnotation(AnnotatedElement element, String annotationType) {
AnnotationAttributes attributes = findAnnotationAttributes(element, annotationType, false, false);
public static <A extends Annotation> A findMergedAnnotation(AnnotatedElement element, String annotationName) {
AnnotationAttributes attributes = findMergedAnnotationAttributes(element, annotationName, false, false);
return ((attributes != null) ? AnnotationUtils.synthesizeAnnotation(attributes,
(Class<A>) 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 <em>above</em> the supplied {@code element} and
* merge that annotation's attributes with <em>matching</em> attributes from
* annotations in lower levels of the annotation hierarchy.
@ -409,14 +428,14 @@ public class AnnotatedElementUtils { @@ -409,14 +428,14 @@ public class AnnotatedElementUtils {
* <p>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.
*
* <p>This method follows <em>find semantics</em> 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 { @@ -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 <strong>all</strong> annotations
* of the specified {@code annotationType} in the annotation hierarchy above
* Get the annotation attributes of <strong>all</strong> annotations of
* the specified {@code annotationName} in the annotation hierarchy above
* the supplied {@link AnnotatedElement} and store the results in a
* {@link MultiValueMap}.
*
* <p>Note: in contrast to {@link #getAnnotationAttributes(AnnotatedElement, String)},
* <p>Note: in contrast to {@link #getMergedAnnotationAttributes(AnnotatedElement, String)},
* this method does <em>not</em> support attribute overrides.
*
* <p>This method follows <em>get semantics</em> 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<String, Object> getAllAnnotationAttributes(AnnotatedElement element, String annotationType) {
return getAllAnnotationAttributes(element, annotationType, false, false);
public static MultiValueMap<String, Object> getAllAnnotationAttributes(AnnotatedElement element, String annotationName) {
return getAllAnnotationAttributes(element, annotationName, false, false);
}
/**
* Get the annotation attributes of <strong>all</strong> annotations
* of the specified {@code annotationType} in the annotation hierarchy above
* Get the annotation attributes of <strong>all</strong> annotations of
* the specified {@code annotationName} in the annotation hierarchy above
* the supplied {@link AnnotatedElement} and store the results in a
* {@link MultiValueMap}.
*
* <p>Note: in contrast to {@link #getAnnotationAttributes(AnnotatedElement, String)},
* <p>Note: in contrast to {@link #getMergedAnnotationAttributes(AnnotatedElement, String)},
* this method does <em>not</em> support attribute overrides.
*
* <p>This method follows <em>get semantics</em> 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 { @@ -488,15 +507,15 @@ public class AnnotatedElementUtils {
* if not found
*/
public static MultiValueMap<String, Object> getAllAnnotationAttributes(AnnotatedElement element,
final String annotationType, final boolean classValuesAsString, final boolean nestedAnnotationsAsMap) {
final String annotationName, final boolean classValuesAsString, final boolean nestedAnnotationsAsMap) {
final MultiValueMap<String, Object> attributesMap = new LinkedMultiValueMap<String, Object>();
searchWithGetSemantics(element, annotationType, new SimpleAnnotationProcessor<Void>() {
searchWithGetSemantics(element, annotationName, new SimpleAnnotationProcessor<Void>() {
@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 { @@ -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 <em>get semantics</em>.
*
* @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> T searchWithGetSemantics(AnnotatedElement element, String annotationType, Processor<T> processor) {
private static <T> T searchWithGetSemantics(AnnotatedElement element, String annotationName, Processor<T> processor) {
try {
return searchWithGetSemantics(element, annotationType, processor, new HashSet<AnnotatedElement>(), 0);
return searchWithGetSemantics(element, annotationName, processor, new HashSet<AnnotatedElement>(), 0);
}
catch (Throwable ex) {
AnnotationUtils.rethrowAnnotationConfigurationException(ex);
@ -543,25 +562,25 @@ public class AnnotatedElementUtils { @@ -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> T searchWithGetSemantics(AnnotatedElement element, String annotationType,
private static <T> T searchWithGetSemantics(AnnotatedElement element, String annotationName,
Processor<T> processor, Set<AnnotatedElement> 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<Annotation> 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 { @@ -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 { @@ -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.
*
* <p>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 { @@ -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> T searchWithGetSemanticsInAnnotations(AnnotatedElement annotatedElement,
List<Annotation> annotations, String annotationType, Processor<T> processor, Set<AnnotatedElement> visited,
int metaDepth) {
private static <T> T searchWithGetSemanticsInAnnotations(AnnotatedElement annotatedElement, List<Annotation> annotations,
String annotationName, Processor<T> processor, Set<AnnotatedElement> 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 { @@ -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 { @@ -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 <em>find semantics</em>.
*
* @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> T searchWithFindSemantics(AnnotatedElement element, String annotationType, Processor<T> processor) {
return searchWithFindSemantics(element, annotationType, true, true, true, true, processor);
private static <T> T searchWithFindSemantics(AnnotatedElement element, String annotationName, Processor<T> 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 <em>find semantics</em>.
*
* @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 { @@ -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> T searchWithFindSemantics(AnnotatedElement element, String annotationType,
private static <T> T searchWithFindSemantics(AnnotatedElement element, String annotationName,
boolean searchOnInterfaces, boolean searchOnSuperclasses, boolean searchOnMethodsInInterfaces,
boolean searchOnMethodsInSuperclasses, Processor<T> processor) {
try {
return searchWithFindSemantics(element, annotationType, searchOnInterfaces, searchOnSuperclasses,
return searchWithFindSemantics(element, annotationName, searchOnInterfaces, searchOnSuperclasses,
searchOnMethodsInInterfaces, searchOnMethodsInSuperclasses, processor, new HashSet<AnnotatedElement>(), 0);
}
catch (Throwable ex) {
@ -697,7 +716,7 @@ public class AnnotatedElementUtils { @@ -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 { @@ -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> T searchWithFindSemantics(AnnotatedElement element, String annotationType,
private static <T> T searchWithFindSemantics(AnnotatedElement element, String annotationName,
boolean searchOnInterfaces, boolean searchOnSuperclasses, boolean searchOnMethodsInInterfaces,
boolean searchOnMethodsInSuperclasses, Processor<T> processor, Set<AnnotatedElement> 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 { @@ -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 { @@ -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 { @@ -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 { @@ -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 { @@ -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 { @@ -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 { @@ -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 { @@ -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 { @@ -846,7 +864,7 @@ public class AnnotatedElementUtils {
return null;
}
private static <T> T searchOnInterfaces(Method method, String annotationType, boolean searchOnInterfaces,
private static <T> T searchOnInterfaces(Method method, String annotationName, boolean searchOnInterfaces,
boolean searchOnSuperclasses, boolean searchOnMethodsInInterfaces, boolean searchOnMethodsInSuperclasses,
Processor<T> processor, Set<AnnotatedElement> visited, int metaDepth, Class<?>[] ifcs) {
@ -854,7 +872,7 @@ public class AnnotatedElementUtils { @@ -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 { @@ -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 { @@ -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<T> implements Processor<T> {
@ -978,21 +996,21 @@ public class AnnotatedElementUtils { @@ -978,21 +996,21 @@ public class AnnotatedElementUtils {
*/
private static class MergedAnnotationAttributesProcessor implements Processor<AnnotationAttributes> {
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);
}

28
spring-core/src/main/java/org/springframework/core/annotation/AnnotationUtils.java

@ -1024,10 +1024,10 @@ public abstract class AnnotationUtils { @@ -1024,10 +1024,10 @@ public abstract class AnnotationUtils {
}
/**
* <em>Synthesize</em> the supplied {@code annotation} by wrapping it in
* a dynamic proxy that transparently enforces <em>attribute alias</em>
* semantics for annotation attributes that are annotated with
* {@link AliasFor @AliasFor}.
* <em>Synthesize</em> an annotation from the supplied {@code annotation}
* by wrapping it in a dynamic proxy that transparently enforces
* <em>attribute alias</em> 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 { @@ -1043,10 +1043,10 @@ public abstract class AnnotationUtils {
}
/**
* <em>Synthesize</em> the supplied {@code annotation} by wrapping it in
* a dynamic proxy that transparently enforces <em>attribute alias</em>
* semantics for annotation attributes that are annotated with
* {@link AliasFor @AliasFor}.
* <em>Synthesize</em> an annotation from the supplied {@code annotation}
* by wrapping it in a dynamic proxy that transparently enforces
* <em>attribute alias</em> 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 { @@ -1083,15 +1083,15 @@ public abstract class AnnotationUtils {
}
/**
* <em>Synthesize</em> the supplied map of annotation attributes by
* wrapping it in a dynamic proxy that implements an annotation of type
* {@code annotationType} and transparently enforces <em>attribute alias</em>
* semantics for annotation attributes that are annotated with
* {@link AliasFor @AliasFor}.
* <em>Synthesize</em> 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 <em>attribute alias</em> semantics for annotation attributes
* that are annotated with {@link AliasFor @AliasFor}.
* <p>The supplied map must contain key-value pairs for every attribute
* defined by the supplied {@code annotationType}.
* <p>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

27
spring-core/src/main/java/org/springframework/core/type/AnnotatedTypeMetadata.java

@ -1,5 +1,5 @@ @@ -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 { @@ -42,27 +42,30 @@ public interface AnnotatedTypeMetadata {
* of the given type defined.
* <p>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<String, Object> getAnnotationAttributes(String annotationType);
Map<String, Object> 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 { @@ -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<String, Object> getAnnotationAttributes(String annotationType, boolean classValuesAsString);
Map<String, Object> 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 <i>not</i> 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<String, Object> getAllAnnotationAttributes(String annotationType);
MultiValueMap<String, Object> 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 <i>not</i> 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<String, Object> getAllAnnotationAttributes(String annotationType, boolean classValuesAsString);
MultiValueMap<String, Object> getAllAnnotationAttributes(String annotationName, boolean classValuesAsString);
}

38
spring-core/src/main/java/org/springframework/core/type/AnnotationMetadata.java

@ -1,5 +1,5 @@ @@ -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; @@ -34,52 +34,58 @@ import java.util.Set;
public interface AnnotationMetadata extends ClassMetadata, AnnotatedTypeMetadata {
/**
* Return the names of all annotation types that are <em>present</em> on the
* underlying class.
* Get the fully qualified class names of all annotation types that
* are <em>present</em> on the underlying class.
* @return the annotation type names
*/
Set<String> getAnnotationTypes();
/**
* Return the names of all meta-annotation types <em>present</em> 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 <em>present</em> 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<String> getMetaAnnotationTypes(String annotationType);
Set<String> getMetaAnnotationTypes(String annotationName);
/**
* Determine whether an annotation of the given type is <em>present</em> 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.
* <p>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<MethodMetadata> getAnnotatedMethods(String annotationType);
Set<MethodMetadata> getAnnotatedMethods(String annotationName);
}

45
spring-core/src/main/java/org/springframework/core/type/StandardAnnotationMetadata.java

@ -1,5 +1,5 @@ @@ -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; @@ -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 @@ -77,15 +78,15 @@ public class StandardAnnotationMetadata extends StandardClassMetadata implements
}
@Override
public Set<String> getMetaAnnotationTypes(String annotationType) {
return AnnotatedElementUtils.getMetaAnnotationTypes(getIntrospectedClass(), annotationType);
public Set<String> 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 @@ -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<String, Object> getAnnotationAttributes(String annotationType) {
return this.getAnnotationAttributes(annotationType, false);
public Map<String, Object> getAnnotationAttributes(String annotationName) {
return this.getAnnotationAttributes(annotationName, false);
}
@Override
public Map<String, Object> getAnnotationAttributes(String annotationType, boolean classValuesAsString) {
return AnnotatedElementUtils.getAnnotationAttributes(getIntrospectedClass(),
annotationType, classValuesAsString, this.nestedAnnotationsAsMap);
public Map<String, Object> getAnnotationAttributes(String annotationName, boolean classValuesAsString) {
return AnnotatedElementUtils.getMergedAnnotationAttributes(getIntrospectedClass(),
annotationName, classValuesAsString, this.nestedAnnotationsAsMap);
}
@Override
public MultiValueMap<String, Object> getAllAnnotationAttributes(String annotationType) {
return getAllAnnotationAttributes(annotationType, false);
public MultiValueMap<String, Object> getAllAnnotationAttributes(String annotationName) {
return getAllAnnotationAttributes(annotationName, false);
}
@Override
public MultiValueMap<String, Object> getAllAnnotationAttributes(String annotationType, boolean classValuesAsString) {
public MultiValueMap<String, Object> 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 @@ -136,11 +137,11 @@ public class StandardAnnotationMetadata extends StandardClassMetadata implements
}
@Override
public Set<MethodMetadata> getAnnotatedMethods(String annotationType) {
public Set<MethodMetadata> getAnnotatedMethods(String annotationName) {
Method[] methods = getIntrospectedClass().getDeclaredMethods();
Set<MethodMetadata> annotatedMethods = new LinkedHashSet<MethodMetadata>();
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));
}
}

23
spring-core/src/main/java/org/springframework/core/type/StandardMethodMetadata.java

@ -73,7 +73,6 @@ public class StandardMethodMetadata implements MethodMetadata { @@ -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 { @@ -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<String, Object> getAnnotationAttributes(String annotationType) {
return getAnnotationAttributes(annotationType, false);
public Map<String, Object> getAnnotationAttributes(String annotationName) {
return getAnnotationAttributes(annotationName, false);
}
@Override
public Map<String, Object> getAnnotationAttributes(String annotationType, boolean classValuesAsString) {
return AnnotatedElementUtils.getAnnotationAttributes(this.introspectedMethod,
annotationType, classValuesAsString, this.nestedAnnotationsAsMap);
public Map<String, Object> getAnnotationAttributes(String annotationName, boolean classValuesAsString) {
return AnnotatedElementUtils.getMergedAnnotationAttributes(this.introspectedMethod,
annotationName, classValuesAsString, this.nestedAnnotationsAsMap);
}
@Override
public MultiValueMap<String, Object> getAllAnnotationAttributes(String annotationType) {
return getAllAnnotationAttributes(annotationType, false);
public MultiValueMap<String, Object> getAllAnnotationAttributes(String annotationName) {
return getAllAnnotationAttributes(annotationName, false);
}
@Override
public MultiValueMap<String, Object> getAllAnnotationAttributes(String annotationType, boolean classValuesAsString) {
public MultiValueMap<String, Object> getAllAnnotationAttributes(String annotationName, boolean classValuesAsString) {
return AnnotatedElementUtils.getAllAnnotationAttributes(this.introspectedMethod,
annotationType, classValuesAsString, this.nestedAnnotationsAsMap);
annotationName, classValuesAsString, this.nestedAnnotationsAsMap);
}
}

37
spring-core/src/main/java/org/springframework/core/type/classreading/AnnotationMetadataReadingVisitor.java

@ -94,13 +94,13 @@ public class AnnotationMetadataReadingVisitor extends ClassMetadataReadingVisito @@ -94,13 +94,13 @@ public class AnnotationMetadataReadingVisitor extends ClassMetadataReadingVisito
}
@Override
public Set<String> getMetaAnnotationTypes(String annotationType) {
return this.metaAnnotationMap.get(annotationType);
public Set<String> 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 @@ -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<String, Object> getAllAnnotationAttributes(String annotationType) {
return getAllAnnotationAttributes(annotationType, false);
public MultiValueMap<String, Object> getAllAnnotationAttributes(String annotationName) {
return getAllAnnotationAttributes(annotationName, false);
}
@Override
public MultiValueMap<String, Object> getAllAnnotationAttributes(String annotationType, boolean classValuesAsString) {
public MultiValueMap<String, Object> getAllAnnotationAttributes(String annotationName, boolean classValuesAsString) {
MultiValueMap<String, Object> allAttributes = new LinkedMultiValueMap<String, Object>();
List<AnnotationAttributes> attributes = this.attributesMap.get(annotationType);
List<AnnotationAttributes> attributes = this.attributesMap.get(annotationName);
if (attributes == null) {
return null;
}
@ -153,9 +154,9 @@ public class AnnotationMetadataReadingVisitor extends ClassMetadataReadingVisito @@ -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 @@ -163,10 +164,10 @@ public class AnnotationMetadataReadingVisitor extends ClassMetadataReadingVisito
}
@Override
public Set<MethodMetadata> getAnnotatedMethods(String annotationType) {
public Set<MethodMetadata> getAnnotatedMethods(String annotationName) {
Set<MethodMetadata> annotatedMethods = new LinkedHashSet<MethodMetadata>(4);
for (MethodMetadata methodMetadata : this.methodMetadataSet) {
if (methodMetadata.isAnnotated(annotationType)) {
if (methodMetadata.isAnnotated(annotationName)) {
annotatedMethods.add(methodMetadata);
}
}

22
spring-core/src/main/java/org/springframework/core/type/classreading/AnnotationReadingVisitorUtils.java

@ -1,5 +1,5 @@ @@ -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; @@ -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 { @@ -102,21 +103,22 @@ abstract class AnnotationReadingVisitorUtils {
* <p>Annotation attribute values appearing <em>lower</em> in the annotation
* hierarchy (i.e., closer to the declaring class) will override those
* defined <em>higher</em> 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<String, AnnotationAttributes> attributesMap,
Map<String, Set<String>> metaAnnotationMap, String annotationType) {
Map<String, Set<String>> metaAnnotationMap, String annotationName) {
// Get the unmerged list of attributes for the target annotation.
List<AnnotationAttributes> attributesList = attributesMap.get(annotationType);
List<AnnotationAttributes> attributesList = attributesMap.get(annotationName);
if (attributesList == null || attributesList.isEmpty()) {
return null;
}
@ -137,13 +139,13 @@ abstract class AnnotationReadingVisitorUtils { @@ -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<AnnotationAttributes> currentAttributesList = attributesMap.get(currentAnnotationType);
if (currentAttributesList != null && !currentAttributesList.isEmpty()) {
if (!ObjectUtils.isEmpty(currentAttributesList)) {
Set<String> 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);

24
spring-core/src/main/java/org/springframework/core/type/classreading/MethodMetadataReadingVisitor.java

@ -31,7 +31,7 @@ import org.springframework.util.LinkedMultiValueMap; @@ -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 @@ -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<String, Object> getAnnotationAttributes(String annotationType) {
return getAnnotationAttributes(annotationType, false);
public Map<String, Object> getAnnotationAttributes(String annotationName) {
return getAnnotationAttributes(annotationName, false);
}
@Override
public Map<String, Object> getAnnotationAttributes(String annotationType, boolean classValuesAsString) {
List<AnnotationAttributes> attributes = this.attributeMap.get(annotationType);
public Map<String, Object> getAnnotationAttributes(String annotationName, boolean classValuesAsString) {
List<AnnotationAttributes> attributes = this.attributeMap.get(annotationName);
return (attributes == null ? null : AnnotationReadingVisitorUtils.convertClassValues(
this.classLoader, attributes.get(0), classValuesAsString));
}
@Override
public MultiValueMap<String, Object> getAllAnnotationAttributes(String annotationType) {
return getAllAnnotationAttributes(annotationType, false);
public MultiValueMap<String, Object> getAllAnnotationAttributes(String annotationName) {
return getAllAnnotationAttributes(annotationName, false);
}
@Override
public MultiValueMap<String, Object> getAllAnnotationAttributes(String annotationType, boolean classValuesAsString) {
if (!this.attributeMap.containsKey(annotationType)) {
public MultiValueMap<String, Object> getAllAnnotationAttributes(String annotationName, boolean classValuesAsString) {
if (!this.attributeMap.containsKey(annotationName)) {
return null;
}
MultiValueMap<String, Object> allAttributes = new LinkedMultiValueMap<String, Object>();
for (AnnotationAttributes annotationAttributes : this.attributeMap.get(annotationType)) {
for (AnnotationAttributes annotationAttributes : this.attributeMap.get(annotationName)) {
for (Map.Entry<String, Object> entry : AnnotationReadingVisitorUtils.convertClassValues(
this.classLoader, annotationAttributes, classValuesAsString).entrySet()) {
allAttributes.add(entry.getKey(), entry.getValue());

118
spring-core/src/test/java/org/springframework/core/annotation/AnnotatedElementUtilsTests.java

@ -190,10 +190,10 @@ public class AnnotatedElementUtilsTests { @@ -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 { @@ -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 { @@ -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 { @@ -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 { @@ -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 { @@ -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 { @@ -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 { @@ -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 { @@ -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 { @@ -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 { @@ -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 { @@ -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 { @@ -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 { @@ -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 { @@ -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 { @@ -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 { @@ -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 { @@ -511,9 +511,9 @@ public class AnnotatedElementUtilsTests {
}
static AnnotationAttributes findAnnotationAttributes(AnnotatedElement element, Class<? extends Annotation> annotationType) {
static AnnotationAttributes findMergedAnnotationAttributes(AnnotatedElement element, Class<? extends Annotation> 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);
}

2
spring-test/src/main/java/org/springframework/test/annotation/TestAnnotationUtils.java

@ -37,7 +37,7 @@ public class TestAnnotationUtils { @@ -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;
}

2
spring-test/src/main/java/org/springframework/test/context/jdbc/MergedSqlConfig.java

@ -86,7 +86,7 @@ class MergedSqlConfig { @@ -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.

2
spring-test/src/main/java/org/springframework/test/context/support/AbstractTestContextBootstrapper.java

@ -137,7 +137,7 @@ public abstract class AbstractTestContextBootstrapper implements TestContextBoot @@ -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()));

2
spring-test/src/main/java/org/springframework/test/context/support/ActiveProfilesUtils.java

@ -86,7 +86,7 @@ abstract class ActiveProfilesUtils { @@ -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,

9
spring-test/src/main/java/org/springframework/test/context/support/ContextLoaderUtils.java

@ -26,6 +26,7 @@ import java.util.Set; @@ -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 { @@ -132,8 +133,10 @@ abstract class ContextLoaderUtils {
final List<ContextConfigurationAttributes> configAttributesList = new ArrayList<ContextConfigurationAttributes>();
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 { @@ -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);
}

2
spring-test/src/main/java/org/springframework/test/context/support/DefaultActiveProfilesResolver.java

@ -73,7 +73,7 @@ public class DefaultActiveProfilesResolver implements ActiveProfilesResolver { @@ -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,

6
spring-test/src/main/java/org/springframework/test/context/support/DirtiesContextTestExecutionListener.java

@ -155,8 +155,8 @@ public class DirtiesContextTestExecutionListener extends AbstractTestExecutionLi @@ -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 @@ -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);

2
spring-test/src/main/java/org/springframework/test/context/support/TestPropertySourceUtils.java

@ -96,7 +96,7 @@ public abstract class TestPropertySourceUtils { @@ -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()) {

2
spring-test/src/main/java/org/springframework/test/context/transaction/TransactionalTestExecutionListener.java

@ -499,7 +499,7 @@ public class TransactionalTestExecutionListener extends AbstractTestExecutionLis @@ -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].",

32
spring-test/src/main/java/org/springframework/test/util/MetaAnnotationUtils.java

@ -272,8 +272,6 @@ public abstract class MetaAnnotationUtils { @@ -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 { @@ -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 { @@ -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<T>) annotation.annotationType(), rootDeclaringClass);
}
public Class<?> getRootDeclaringClass() {
@ -309,13 +304,18 @@ public abstract class MetaAnnotationUtils { @@ -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<T>) getAnnotationType(),
getRootDeclaringClass());
}
public Class<? extends Annotation> getAnnotationType() {
@ -364,6 +364,18 @@ public abstract class MetaAnnotationUtils { @@ -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");
}
}
}

4
spring-tx/src/main/java/org/springframework/transaction/annotation/JtaTransactionAnnotationParser.java

@ -1,5 +1,5 @@ @@ -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 @@ -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);
}

4
spring-tx/src/main/java/org/springframework/transaction/annotation/SpringTransactionAnnotationParser.java

@ -1,5 +1,5 @@ @@ -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 @@ -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);
}

5
spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/MvcUriComponentsBuilder.java

@ -418,7 +418,7 @@ public class MvcUriComponentsBuilder { @@ -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 { @@ -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());
}

2
spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/RequestMappingHandlerMapping.java

@ -209,7 +209,7 @@ public class RequestMappingHandlerMapping extends RequestMappingInfoHandlerMappi @@ -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));

Loading…
Cancel
Save