30
30
31
31
import org .springframework .core .BridgeMethodResolver ;
32
32
import org .springframework .lang .Nullable ;
33
+ import org .springframework .util .CollectionUtils ;
33
34
import org .springframework .util .LinkedMultiValueMap ;
34
35
import org .springframework .util .MultiValueMap ;
35
36
@@ -232,7 +233,6 @@ private static boolean hasMetaAnnotationTypes(AnnotatedElement element, @Nullabl
232
233
233
234
return Boolean .TRUE .equals (
234
235
searchWithGetSemantics (element , annotationType , annotationName , new SimpleAnnotationProcessor <Boolean >() {
235
-
236
236
@ Override
237
237
@ Nullable
238
238
public Boolean process (@ Nullable AnnotatedElement annotatedElement , Annotation annotation , int metaDepth ) {
@@ -950,7 +950,7 @@ else if (currentAnnotationType == containerType) {
950
950
// Recursively search in meta-annotations
951
951
for (Annotation annotation : annotations ) {
952
952
Class <? extends Annotation > currentAnnotationType = annotation .annotationType ();
953
- if (! AnnotationUtils . isInJavaLangAnnotationPackage (currentAnnotationType )) {
953
+ if (hasSearchableMetaAnnotations (currentAnnotationType , annotationType , annotationName )) {
954
954
T result = searchWithGetSemantics (currentAnnotationType , annotationType ,
955
955
annotationName , containerType , processor , visited , metaDepth + 1 );
956
956
if (result != null ) {
@@ -1083,10 +1083,10 @@ else if (currentAnnotationType == containerType) {
1083
1083
}
1084
1084
}
1085
1085
1086
- // Search in meta annotations on local annotations
1086
+ // Recursively search in meta- annotations
1087
1087
for (Annotation annotation : annotations ) {
1088
1088
Class <? extends Annotation > currentAnnotationType = annotation .annotationType ();
1089
- if (! AnnotationUtils . isInJavaLangAnnotationPackage (currentAnnotationType )) {
1089
+ if (hasSearchableMetaAnnotations (currentAnnotationType , annotationType , annotationName )) {
1090
1090
T result = searchWithFindSemantics (currentAnnotationType , annotationType , annotationName ,
1091
1091
containerType , processor , visited , metaDepth + 1 );
1092
1092
if (result != null ) {
@@ -1101,28 +1101,33 @@ else if (currentAnnotationType == containerType) {
1101
1101
}
1102
1102
}
1103
1103
1104
- if (aggregatedResults != null ) {
1104
+ if (! CollectionUtils . isEmpty ( aggregatedResults ) ) {
1105
1105
// Prepend to support top-down ordering within class hierarchies
1106
1106
processor .getAggregatedResults ().addAll (0 , aggregatedResults );
1107
1107
}
1108
1108
1109
1109
if (element instanceof Method ) {
1110
1110
Method method = (Method ) element ;
1111
+ T result ;
1111
1112
1112
1113
// Search on possibly bridged method
1113
1114
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
+ }
1118
1121
}
1119
1122
1120
1123
// Search on methods in interfaces declared locally
1121
1124
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
+ }
1126
1131
}
1127
1132
1128
1133
// Search on methods in class hierarchy and interface hierarchy
@@ -1189,10 +1194,10 @@ private static <T> T searchOnInterfaces(Method method, @Nullable Class<? extends
1189
1194
@ Nullable String annotationName , @ Nullable Class <? extends Annotation > containerType ,
1190
1195
Processor <T > processor , Set <AnnotatedElement > visited , int metaDepth , Class <?>[] ifcs ) {
1191
1196
1192
- for (Class <?> iface : ifcs ) {
1193
- if (AnnotationUtils .isInterfaceWithAnnotatedMethods (iface )) {
1197
+ for (Class <?> ifc : ifcs ) {
1198
+ if (AnnotationUtils .isInterfaceWithAnnotatedMethods (ifc )) {
1194
1199
try {
1195
- Method equivalentMethod = iface .getMethod (method .getName (), method .getParameterTypes ());
1200
+ Method equivalentMethod = ifc .getMethod (method .getName (), method .getParameterTypes ());
1196
1201
T result = searchWithFindSemantics (equivalentMethod , annotationType , annotationName , containerType ,
1197
1202
processor , visited , metaDepth );
1198
1203
if (result != null ) {
@@ -1208,6 +1213,26 @@ private static <T> T searchOnInterfaces(Method method, @Nullable Class<? extends
1208
1213
return null ;
1209
1214
}
1210
1215
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
+
1211
1236
/**
1212
1237
* Get the array of raw (unsynthesized) annotations from the {@code value}
1213
1238
* attribute of the supplied repeatable annotation {@code container}.
0 commit comments