diff --git a/spring-core/src/main/java/org/springframework/core/annotation/RepeatableContainers.java b/spring-core/src/main/java/org/springframework/core/annotation/RepeatableContainers.java index 9564e1cbe6e1..e1f7f9f72297 100644 --- a/spring-core/src/main/java/org/springframework/core/annotation/RepeatableContainers.java +++ b/spring-core/src/main/java/org/springframework/core/annotation/RepeatableContainers.java @@ -18,7 +18,9 @@ import java.lang.annotation.Annotation; import java.lang.annotation.Repeatable; +import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; +import java.lang.reflect.Proxy; import java.util.Map; import org.springframework.lang.Nullable; @@ -131,6 +133,19 @@ public static RepeatableContainers none() { return NoRepeatableContainers.INSTANCE; } + private static Object invokeAnnotationMethod(Annotation annotation, Method method) { + if (Proxy.isProxyClass(annotation.getClass())) { + try { + InvocationHandler handler = Proxy.getInvocationHandler(annotation); + return handler.invoke(annotation, method, null); + } + catch (Throwable ex) { + // ignore and fall back to reflection below + } + } + return ReflectionUtils.invokeMethod(method, annotation); + } + /** * Standard {@link RepeatableContainers} implementation that searches using @@ -153,7 +168,7 @@ private static class StandardRepeatableContainers extends RepeatableContainers { Annotation[] findRepeatedAnnotations(Annotation annotation) { Method method = getRepeatedAnnotationsMethod(annotation.annotationType()); if (method != null) { - return (Annotation[]) ReflectionUtils.invokeMethod(method, annotation); + return (Annotation[]) invokeAnnotationMethod(annotation, method); } return super.findRepeatedAnnotations(annotation); } @@ -240,7 +255,7 @@ private Class deduceContainer(Class @Nullable Annotation[] findRepeatedAnnotations(Annotation annotation) { if (this.container.isAssignableFrom(annotation.annotationType())) { - return (Annotation[]) ReflectionUtils.invokeMethod(this.valueMethod, annotation); + return (Annotation[]) invokeAnnotationMethod(annotation, this.valueMethod); } return super.findRepeatedAnnotations(annotation); } diff --git a/spring-core/src/test/java/org/springframework/core/annotation/NestedRepeatableAnnotationsTests.java b/spring-core/src/test/java/org/springframework/core/annotation/NestedRepeatableAnnotationsTests.java index 1fe1a6fe8b09..2f99db0018dc 100644 --- a/spring-core/src/test/java/org/springframework/core/annotation/NestedRepeatableAnnotationsTests.java +++ b/spring-core/src/test/java/org/springframework/core/annotation/NestedRepeatableAnnotationsTests.java @@ -181,7 +181,7 @@ void annotatedMethod() { @Retention(RetentionPolicy.RUNTIME) @Target({ ElementType.METHOD, ElementType.ANNOTATION_TYPE }) @Repeatable(A.Container.class) - public @interface A { + @interface A { int value() default 0; @@ -197,7 +197,7 @@ void annotatedMethod() { @Repeatable(B.Container.class) @A @A - public @interface B { + @interface B { @AliasFor(annotation = A.class) int value();