3030
3131import org .springframework .core .BridgeMethodResolver ;
3232import org .springframework .lang .Nullable ;
33+ import org .springframework .util .CollectionUtils ;
3334import org .springframework .util .LinkedMultiValueMap ;
3435import org .springframework .util .MultiValueMap ;
3536
@@ -232,7 +233,6 @@ private static boolean hasMetaAnnotationTypes(AnnotatedElement element, @Nullabl
232233
233234 return Boolean .TRUE .equals (
234235 searchWithGetSemantics (element , annotationType , annotationName , new SimpleAnnotationProcessor <Boolean >() {
235-
236236 @ Override
237237 @ Nullable
238238 public Boolean process (@ Nullable AnnotatedElement annotatedElement , Annotation annotation , int metaDepth ) {
@@ -950,7 +950,7 @@ else if (currentAnnotationType == containerType) {
950950 // Recursively search in meta-annotations
951951 for (Annotation annotation : annotations ) {
952952 Class <? extends Annotation > currentAnnotationType = annotation .annotationType ();
953- if (! AnnotationUtils . isInJavaLangAnnotationPackage (currentAnnotationType )) {
953+ if (hasSearchableMetaAnnotations (currentAnnotationType , annotationType , annotationName )) {
954954 T result = searchWithGetSemantics (currentAnnotationType , annotationType ,
955955 annotationName , containerType , processor , visited , metaDepth + 1 );
956956 if (result != null ) {
@@ -1083,10 +1083,10 @@ else if (currentAnnotationType == containerType) {
10831083 }
10841084 }
10851085
1086- // Search in meta annotations on local annotations
1086+ // Recursively search in meta- annotations
10871087 for (Annotation annotation : annotations ) {
10881088 Class <? extends Annotation > currentAnnotationType = annotation .annotationType ();
1089- if (! AnnotationUtils . isInJavaLangAnnotationPackage (currentAnnotationType )) {
1089+ if (hasSearchableMetaAnnotations (currentAnnotationType , annotationType , annotationName )) {
10901090 T result = searchWithFindSemantics (currentAnnotationType , annotationType , annotationName ,
10911091 containerType , processor , visited , metaDepth + 1 );
10921092 if (result != null ) {
@@ -1101,28 +1101,33 @@ else if (currentAnnotationType == containerType) {
11011101 }
11021102 }
11031103
1104- if (aggregatedResults != null ) {
1104+ if (! CollectionUtils . isEmpty ( aggregatedResults ) ) {
11051105 // Prepend to support top-down ordering within class hierarchies
11061106 processor .getAggregatedResults ().addAll (0 , aggregatedResults );
11071107 }
11081108
11091109 if (element instanceof Method ) {
11101110 Method method = (Method ) element ;
1111+ T result ;
11111112
11121113 // Search on possibly bridged method
11131114 Method resolvedMethod = BridgeMethodResolver .findBridgedMethod (method );
1114- T result = searchWithFindSemantics (resolvedMethod , annotationType , annotationName , containerType ,
1115- processor , visited , metaDepth );
1116- if (result != null ) {
1117- return result ;
1115+ if (resolvedMethod != method ) {
1116+ result = searchWithFindSemantics (resolvedMethod , annotationType , annotationName ,
1117+ containerType , processor , visited , metaDepth );
1118+ if (result != null ) {
1119+ return result ;
1120+ }
11181121 }
11191122
11201123 // Search on methods in interfaces declared locally
11211124 Class <?>[] ifcs = method .getDeclaringClass ().getInterfaces ();
1122- result = searchOnInterfaces (method , annotationType , annotationName , containerType , processor ,
1123- visited , metaDepth , ifcs );
1124- if (result != null ) {
1125- return result ;
1125+ if (ifcs .length > 0 ) {
1126+ result = searchOnInterfaces (method , annotationType , annotationName , containerType ,
1127+ processor , visited , metaDepth , ifcs );
1128+ if (result != null ) {
1129+ return result ;
1130+ }
11261131 }
11271132
11281133 // Search on methods in class hierarchy and interface hierarchy
@@ -1189,10 +1194,10 @@ private static <T> T searchOnInterfaces(Method method, @Nullable Class<? extends
11891194 @ Nullable String annotationName , @ Nullable Class <? extends Annotation > containerType ,
11901195 Processor <T > processor , Set <AnnotatedElement > visited , int metaDepth , Class <?>[] ifcs ) {
11911196
1192- for (Class <?> iface : ifcs ) {
1193- if (AnnotationUtils .isInterfaceWithAnnotatedMethods (iface )) {
1197+ for (Class <?> ifc : ifcs ) {
1198+ if (AnnotationUtils .isInterfaceWithAnnotatedMethods (ifc )) {
11941199 try {
1195- Method equivalentMethod = iface .getMethod (method .getName (), method .getParameterTypes ());
1200+ Method equivalentMethod = ifc .getMethod (method .getName (), method .getParameterTypes ());
11961201 T result = searchWithFindSemantics (equivalentMethod , annotationType , annotationName , containerType ,
11971202 processor , visited , metaDepth );
11981203 if (result != null ) {
@@ -1208,6 +1213,26 @@ private static <T> T searchOnInterfaces(Method method, @Nullable Class<? extends
12081213 return null ;
12091214 }
12101215
1216+ /**
1217+ * Determine whether the current annotation type is generally expected to have
1218+ * meta-annotations of the specified annotation type that we're searching for,
1219+ * explicitly excluding some common cases that would never deliver any results.
1220+ */
1221+ private static boolean hasSearchableMetaAnnotations (Class <? extends Annotation > currentAnnotationType ,
1222+ @ Nullable Class <?> annotationType , @ Nullable String annotationName ) {
1223+
1224+ if (AnnotationUtils .isInJavaLangAnnotationPackage (currentAnnotationType )) {
1225+ return false ;
1226+ }
1227+ if (currentAnnotationType == Nullable .class || currentAnnotationType .getName ().startsWith ("java" )) {
1228+ // @Nullable and standard Java annotations are only meant to have standard Java meta-annotations
1229+ // -> not worth searching otherwise.
1230+ return ((annotationType != null && annotationType .getName ().startsWith ("java" )) ||
1231+ (annotationName != null && annotationName .startsWith ("java" )));
1232+ }
1233+ return true ;
1234+ }
1235+
12111236 /**
12121237 * Get the array of raw (unsynthesized) annotations from the {@code value}
12131238 * attribute of the supplied repeatable annotation {@code container}.
0 commit comments