diff --git a/spring-context/src/main/java/org/springframework/scheduling/annotation/ScheduledAnnotationBeanPostProcessor.java b/spring-context/src/main/java/org/springframework/scheduling/annotation/ScheduledAnnotationBeanPostProcessor.java index 6131aba8ad..591ae6a350 100644 --- a/spring-context/src/main/java/org/springframework/scheduling/annotation/ScheduledAnnotationBeanPostProcessor.java +++ b/spring-context/src/main/java/org/springframework/scheduling/annotation/ScheduledAnnotationBeanPostProcessor.java @@ -224,7 +224,7 @@ public class ScheduledAnnotationBeanPostProcessor implements BeanPostProcessor, @Override public void doWith(Method method) throws IllegalArgumentException, IllegalAccessException { for (Scheduled scheduled : - AnnotationUtils.getRepeatableAnnotation(method, Schedules.class, Scheduled.class)) { + AnnotationUtils.getRepeatableAnnotations(method, Schedules.class, Scheduled.class)) { processScheduled(scheduled, method, bean); annotatedMethods.add(method); } diff --git a/spring-core/src/main/java/org/springframework/core/annotation/AnnotationUtils.java b/spring-core/src/main/java/org/springframework/core/annotation/AnnotationUtils.java index 7d16c256df..d6f2082c79 100644 --- a/spring-core/src/main/java/org/springframework/core/annotation/AnnotationUtils.java +++ b/spring-core/src/main/java/org/springframework/core/annotation/AnnotationUtils.java @@ -61,8 +61,9 @@ import org.springframework.util.StringUtils; * inheritance hierarchy of the given method ({@link #findAnnotation(Method, Class)}). * *
An annotation is meta-present on an element if the annotation * is declared as a meta-annotation on some other annotation which is @@ -248,53 +249,125 @@ public abstract class AnnotationUtils { } /** - * Get the repeatable {@link Annotation}s of {@code annotationType} - * from the supplied {@link Method}, where such annotations are either - * present or meta-present on the method. - *
Handles both single annotations and annotations nested within a - * containing annotation. - *
Correctly handles bridge {@link Method Methods} generated by the compiler. - *
Meta-annotations will be searched if the annotation is not
- * present on the supplied method.
- * @param method the method to look for annotations on; never {@code null}
- * @param containerAnnotationType the type of the container that holds the
- * annotations; may be {@code null} if a container is not supported
- * @param annotationType the annotation type to look for
- * @return the annotations found or an empty set; never {@code null}
+ * Delegates to {@link #getRepeatableAnnotations}.
* @since 4.0
- * @see org.springframework.core.BridgeMethodResolver#findBridgedMethod(Method)
- * @see java.lang.annotation.Repeatable
+ * @deprecated As of Spring Framework 4.2, use {@link #getRepeatableAnnotations}
+ * or {@link #getDeclaredRepeatableAnnotations} instead.
*/
+ @Deprecated
public static Set getRepeatableAnnotation(Method method,
Class extends Annotation> containerAnnotationType, Class annotationType) {
-
- Method resolvedMethod = BridgeMethodResolver.findBridgedMethod(method);
- return getRepeatableAnnotation((AnnotatedElement) resolvedMethod, containerAnnotationType, annotationType);
+ return getRepeatableAnnotations(method, containerAnnotationType, annotationType);
}
/**
- * Get the repeatable {@link Annotation}s of {@code annotationType}
- * from the supplied {@link AnnotatedElement}, where such annotations are
- * either present or meta-present on the element.
+ * Delegates to {@link #getRepeatableAnnotations}.
+ * @since 4.0
+ * @deprecated As of Spring Framework 4.2, use {@link #getRepeatableAnnotations}
+ * or {@link #getDeclaredRepeatableAnnotations} instead.
+ */
+ @Deprecated
+ public static Set getRepeatableAnnotation(AnnotatedElement annotatedElement,
+ Class extends Annotation> containerAnnotationType, Class annotationType) {
+ return getRepeatableAnnotations(annotatedElement, containerAnnotationType, annotationType);
+ }
+
+ /**
+ * Get the repeatable {@linkplain Annotation annotations} of
+ * {@code annotationType} from the supplied {@link AnnotatedElement}, where
+ * such annotations are either present or meta-present
+ * on the element.
+ * This method mimics the functionality of Java 8's
+ * {@link java.lang.reflect.AnnotatedElement#getAnnotationsByType(Class)}
+ * with additional support for meta-annotations.
* Handles both single annotations and annotations nested within a
- * containing annotation.
+ * container annotation.
+ * Correctly handles bridge methods generated by the
+ * compiler if the supplied element is a {@link Method}.
* Meta-annotations will be searched if the annotation is not
* present on the supplied element.
* @param annotatedElement the element to look for annotations on; never {@code null}
- * @param containerAnnotationType the type of the container that holds the
- * annotations; may be {@code null} if a container is not supported
- * @param annotationType the annotation type to look for
+ * @param containerAnnotationType the type of the container that holds
+ * the annotations; may be {@code null} if a container is not supported
+ * @param annotationType the annotation type to look for; never {@code null}
* @return the annotations found or an empty set; never {@code null}
- * @since 4.0
+ * @since 4.2
+ * @see #getDeclaredRepeatableAnnotations(AnnotatedElement, Class, Class)
+ * @see org.springframework.core.BridgeMethodResolver#findBridgedMethod
* @see java.lang.annotation.Repeatable
+ * @see java.lang.reflect.AnnotatedElement#getAnnotationsByType
*/
- public static Set getRepeatableAnnotation(AnnotatedElement annotatedElement,
+ public static Set getRepeatableAnnotations(AnnotatedElement annotatedElement,
Class extends Annotation> containerAnnotationType, Class annotationType) {
+ Set annotations = getDeclaredRepeatableAnnotations(annotatedElement, containerAnnotationType, annotationType);
+ if (!annotations.isEmpty()) {
+ return annotations;
+ }
+
+ return getRepeatableAnnotations(annotatedElement, containerAnnotationType, annotationType, false);
+ }
+
+ /**
+ * Get the declared repeatable {@linkplain Annotation annotations}
+ * of {@code annotationType} from the supplied {@link AnnotatedElement},
+ * where such annotations are either directly present,
+ * indirectly present, or meta-present on the element.
+ * This method mimics the functionality of Java 8's
+ * {@link java.lang.reflect.AnnotatedElement#getDeclaredAnnotationsByType(Class)}
+ * with additional support for meta-annotations.
+ * Handles both single annotations and annotations nested within a
+ * container annotation.
+ * Correctly handles bridge methods generated by the
+ * compiler if the supplied element is a {@link Method}.
+ * Meta-annotations will be searched if the annotation is not
+ * present on the supplied element.
+ * @param annotatedElement the element to look for annotations on; never {@code null}
+ * @param containerAnnotationType the type of the container that holds
+ * the annotations; may be {@code null} if a container is not supported
+ * @param annotationType the annotation type to look for; never {@code null}
+ * @return the annotations found or an empty set; never {@code null}
+ * @since 4.2
+ * @see #getRepeatableAnnotations(AnnotatedElement, Class, Class)
+ * @see org.springframework.core.BridgeMethodResolver#findBridgedMethod
+ * @see java.lang.annotation.Repeatable
+ * @see java.lang.reflect.AnnotatedElement#getDeclaredAnnotationsByType
+ */
+ public static Set getDeclaredRepeatableAnnotations(AnnotatedElement annotatedElement,
+ Class extends Annotation> containerAnnotationType, Class annotationType) {
+ return getRepeatableAnnotations(annotatedElement, containerAnnotationType, annotationType, true);
+ }
+
+ /**
+ * Perform the actual work for {@link #getRepeatableAnnotations(AnnotatedElement, Class, Class)}
+ * and {@link #getDeclaredRepeatableAnnotations(AnnotatedElement, Class, Class)}.
+ * Correctly handles bridge methods generated by the
+ * compiler if the supplied element is a {@link Method}.
+ * Meta-annotations will be searched if the annotation is not
+ * present on the supplied element.
+ *
+ * @param annotatedElement the element to look for annotations on; never {@code null}
+ * @param containerAnnotationType the type of the container that holds
+ * the annotations; may be {@code null} if a container is not supported
+ * @param annotationType the annotation type to look for; never {@code null}
+ * @param declaredMode {@code true} if only declared annotations (i.e.,
+ * directly or indirectly present) should be considered.
+ * @return the annotations found or an empty set; never {@code null}
+ * @since 4.2
+ * @see org.springframework.core.BridgeMethodResolver#findBridgedMethod
+ * @see java.lang.annotation.Repeatable
+ */
+ private static Set getRepeatableAnnotations(AnnotatedElement annotatedElement,
+ Class extends Annotation> containerAnnotationType, Class annotationType, boolean declaredMode) {
+
+ Assert.notNull(annotatedElement, "annotatedElement must not be null");
+ Assert.notNull(annotationType, "annotationType must not be null");
+
try {
- if (annotatedElement.getAnnotations().length > 0) {
- return new AnnotationCollector(containerAnnotationType, annotationType).getResult(annotatedElement);
+ if (annotatedElement instanceof Method) {
+ annotatedElement = BridgeMethodResolver.findBridgedMethod((Method) annotatedElement);
}
+ return new AnnotationCollector(containerAnnotationType, annotationType, declaredMode).getResult(annotatedElement);
}
catch (Exception ex) {
handleIntrospectionFailure(annotatedElement, ex);
@@ -1596,16 +1669,20 @@ public abstract class AnnotationUtils {
private final Class annotationType;
+ private final boolean declaredMode;
+
private final Set