diff --git a/spring-core/src/main/java/org/springframework/core/annotation/AnnotatedMethod.java b/spring-core/src/main/java/org/springframework/core/annotation/AnnotatedMethod.java index bed13c555c3..2fb34cf7f54 100644 --- a/spring-core/src/main/java/org/springframework/core/annotation/AnnotatedMethod.java +++ b/spring-core/src/main/java/org/springframework/core/annotation/AnnotatedMethod.java @@ -22,6 +22,8 @@ import java.lang.reflect.Modifier; import java.util.ArrayList; import java.util.Arrays; import java.util.List; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; import org.jspecify.annotations.Nullable; @@ -48,12 +50,16 @@ import org.springframework.util.StringUtils; */ public class AnnotatedMethod { + private static final Object NO_ANNOTATION = new Object(); + private final Method method; private final Method bridgedMethod; private final MethodParameter[] parameters; + private final Map, Object> annotations = new ConcurrentHashMap<>(4); + private volatile @Nullable List inheritedParameterAnnotations; @@ -149,8 +155,13 @@ public class AnnotatedMethod { * @return the annotation, or {@code null} if none found * @see AnnotatedElementUtils#findMergedAnnotation */ + @SuppressWarnings("unchecked") public @Nullable A getMethodAnnotation(Class annotationType) { - return AnnotatedElementUtils.findMergedAnnotation(this.method, annotationType); + Object result = this.annotations.computeIfAbsent(annotationType, key -> { + Object value = AnnotatedElementUtils.findMergedAnnotation(this.method, annotationType); + return (value == null ? NO_ANNOTATION : value); + }); + return (result == NO_ANNOTATION ? null : (A) result); } /** @@ -160,7 +171,7 @@ public class AnnotatedMethod { * @see AnnotatedElementUtils#hasAnnotation */ public boolean hasMethodAnnotation(Class annotationType) { - return AnnotatedElementUtils.hasAnnotation(this.method, annotationType); + return (getMethodAnnotation(annotationType) != null); } private List getInheritedParameterAnnotations() {