diff --git a/spring-beans/src/main/java/org/springframework/beans/factory/annotation/AutowiredAnnotationBeanPostProcessor.java b/spring-beans/src/main/java/org/springframework/beans/factory/annotation/AutowiredAnnotationBeanPostProcessor.java index fe5fa3336af..b610cbd6b9a 100644 --- a/spring-beans/src/main/java/org/springframework/beans/factory/annotation/AutowiredAnnotationBeanPostProcessor.java +++ b/spring-beans/src/main/java/org/springframework/beans/factory/annotation/AutowiredAnnotationBeanPostProcessor.java @@ -442,9 +442,9 @@ public class AutowiredAnnotationBeanPostProcessor extends InstantiationAwareBean private AnnotationAttributes findAutowiredAnnotation(AccessibleObject ao) { for (Class extends Annotation> type : this.autowiredAnnotationTypes) { - AnnotationAttributes ann = AnnotatedElementUtils.getAnnotationAttributes(ao, type.getName()); - if (ann != null) { - return ann; + AnnotationAttributes attributes = AnnotatedElementUtils.getAnnotationAttributes(ao, type); + if (attributes != null) { + return attributes; } } return null; diff --git a/spring-core/src/main/java/org/springframework/core/annotation/AnnotatedElementUtils.java b/spring-core/src/main/java/org/springframework/core/annotation/AnnotatedElementUtils.java index 3428966d364..5f2c3341ad9 100644 --- a/spring-core/src/main/java/org/springframework/core/annotation/AnnotatedElementUtils.java +++ b/spring-core/src/main/java/org/springframework/core/annotation/AnnotatedElementUtils.java @@ -218,6 +218,31 @@ public class AnnotatedElementUtils { })); } + /** + * Get the first annotation of the specified {@code annotationType} within + * the annotation hierarchy above the supplied {@code element} and + * merge that annotation's attributes with matching attributes from + * annotations in lower levels of the annotation hierarchy. + * + *
{@link AliasFor @AliasFor} semantics are fully supported, both + * within a single annotation and within the annotation hierarchy. + * + *
This method delegates to {@link #getAnnotationAttributes(AnnotatedElement, String)}. + * + * @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 + * @see #getAnnotationAttributes(AnnotatedElement, String, boolean, boolean) + * @see #getAllAnnotationAttributes(AnnotatedElement, String) + * @see #findAnnotationAttributes(AnnotatedElement, String, boolean, boolean) + * @see #findAnnotation(AnnotatedElement, Class) + */ + public static AnnotationAttributes getAnnotationAttributes(AnnotatedElement element, + Class extends Annotation> annotationType) { + Assert.notNull(annotationType, "annotationType must not be null"); + return getAnnotationAttributes(element, annotationType.getName()); + } + /** * Get the first annotation of the specified {@code annotationType} within * the annotation hierarchy above the supplied {@code element} and @@ -298,9 +323,7 @@ public class AnnotatedElementUtils { *
{@link AliasFor @AliasFor} semantics are fully supported, both * within a single annotation and within the annotation hierarchy. * - *
This method delegates to {@link #findAnnotationAttributes(AnnotatedElement, String, boolean, boolean)} - * (supplying {@code false} for {@code classValuesAsString} and {@code nestedAnnotationsAsMap}) - * and {@link AnnotationUtils#synthesizeAnnotation(Map, Class, AnnotatedElement)}. + *
This method delegates to {@link #findAnnotation(AnnotatedElement, String)}. * * @param element the annotated element; never {@code null} * @param annotationType the annotation type to find; never {@code null} @@ -308,7 +331,7 @@ public class AnnotatedElementUtils { * @since 4.2 * @see #findAnnotation(AnnotatedElement, String) * @see #findAnnotationAttributes(AnnotatedElement, String, boolean, boolean) - * @see AnnotationUtils#synthesizeAnnotation(Map, Class, AnnotatedElement) + * @see #getAnnotationAttributes(AnnotatedElement, Class) */ public static A findAnnotation(AnnotatedElement element, Class annotationType) { Assert.notNull(annotationType, "annotationType must not be null"); diff --git a/spring-core/src/test/java/org/springframework/core/annotation/AnnotatedElementUtilsTests.java b/spring-core/src/test/java/org/springframework/core/annotation/AnnotatedElementUtilsTests.java index 5e677315df7..3b80dc6f6ff 100644 --- a/spring-core/src/test/java/org/springframework/core/annotation/AnnotatedElementUtilsTests.java +++ b/spring-core/src/test/java/org/springframework/core/annotation/AnnotatedElementUtilsTests.java @@ -325,8 +325,6 @@ public class AnnotatedElementUtilsTests { @Test public void getAnnotationAttributesWithInvalidConventionBasedComposedAnnotation() { Class> element = InvalidConventionBasedComposedContextConfigClass.class; - String name = ContextConfig.class.getName(); - exception.expect(AnnotationConfigurationException.class); exception.expectMessage(either(containsString("attribute [value] and its alias [locations]")).or( containsString("attribute [locations] and its alias [value]"))); @@ -334,21 +332,19 @@ 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, name); + getAnnotationAttributes(element, ContextConfig.class); } @Test public void getAnnotationAttributesWithInvalidAliasedComposedAnnotation() { Class> element = InvalidAliasedComposedContextConfigClass.class; - String name = ContextConfig.class.getName(); - exception.expect(AnnotationConfigurationException.class); exception.expectMessage(either(containsString("attribute [value] and its alias [locations]")).or( containsString("attribute [locations] and its alias [value]"))); 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, name); + getAnnotationAttributes(element, ContextConfig.class); } @Test diff --git a/spring-tx/src/main/java/org/springframework/transaction/annotation/JtaTransactionAnnotationParser.java b/spring-tx/src/main/java/org/springframework/transaction/annotation/JtaTransactionAnnotationParser.java index 8b05331450f..e8c76af63dc 100644 --- a/spring-tx/src/main/java/org/springframework/transaction/annotation/JtaTransactionAnnotationParser.java +++ b/spring-tx/src/main/java/org/springframework/transaction/annotation/JtaTransactionAnnotationParser.java @@ -39,9 +39,9 @@ public class JtaTransactionAnnotationParser implements TransactionAnnotationPars @Override public TransactionAttribute parseTransactionAnnotation(AnnotatedElement ae) { - AnnotationAttributes ann = AnnotatedElementUtils.getAnnotationAttributes(ae, javax.transaction.Transactional.class.getName()); - if (ann != null) { - return parseTransactionAnnotation(ann); + AnnotationAttributes attributes = AnnotatedElementUtils.getAnnotationAttributes(ae, javax.transaction.Transactional.class); + if (attributes != null) { + return parseTransactionAnnotation(attributes); } else { return null; diff --git a/spring-tx/src/main/java/org/springframework/transaction/annotation/SpringTransactionAnnotationParser.java b/spring-tx/src/main/java/org/springframework/transaction/annotation/SpringTransactionAnnotationParser.java index 60ae9b8fdac..c6eda305734 100644 --- a/spring-tx/src/main/java/org/springframework/transaction/annotation/SpringTransactionAnnotationParser.java +++ b/spring-tx/src/main/java/org/springframework/transaction/annotation/SpringTransactionAnnotationParser.java @@ -39,9 +39,9 @@ public class SpringTransactionAnnotationParser implements TransactionAnnotationP @Override public TransactionAttribute parseTransactionAnnotation(AnnotatedElement ae) { - AnnotationAttributes ann = AnnotatedElementUtils.getAnnotationAttributes(ae, Transactional.class.getName()); - if (ann != null) { - return parseTransactionAnnotation(ann); + AnnotationAttributes attributes = AnnotatedElementUtils.getAnnotationAttributes(ae, Transactional.class); + if (attributes != null) { + return parseTransactionAnnotation(attributes); } else { return null;