Skip to content

Commit 2b3fdfa

Browse files
committed
Remove unused class filtering support in AnnotationScanner
PR gh-25429 brought it to our attention that there was a bug in AnnotationScanner when using a non-null class filter that filtered out classes; however, it turns out that there is no production code that utilizes the package-private class filtering support. This commit therefore removes all class filtering support from AnnotationScanner since that functionality is effectively unused. Closes gh-25477
1 parent 5442d87 commit 2b3fdfa

File tree

2 files changed

+40
-139
lines changed

2 files changed

+40
-139
lines changed

spring-core/src/main/java/org/springframework/core/annotation/AnnotationsScanner.java

Lines changed: 40 additions & 94 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@
2323
import java.lang.reflect.Modifier;
2424
import java.util.Arrays;
2525
import java.util.Map;
26-
import java.util.function.BiPredicate;
2726

2827
import org.springframework.core.BridgeMethodResolver;
2928
import org.springframework.core.Ordered;
@@ -75,70 +74,49 @@ private AnnotationsScanner() {
7574
static <C, R> R scan(C context, AnnotatedElement source, SearchStrategy searchStrategy,
7675
AnnotationsProcessor<C, R> processor) {
7776

78-
return scan(context, source, searchStrategy, processor, null);
79-
}
80-
81-
/**
82-
* Scan the hierarchy of the specified element for relevant annotations and
83-
* call the processor as required.
84-
* @param context an optional context object that will be passed back to the
85-
* processor
86-
* @param source the source element to scan
87-
* @param searchStrategy the search strategy to use
88-
* @param processor the processor that receives the annotations
89-
* @param classFilter an optional filter that can be used to entirely filter
90-
* out a specific class from the hierarchy
91-
* @return the result of {@link AnnotationsProcessor#finish(Object)}
92-
*/
93-
@Nullable
94-
static <C, R> R scan(C context, AnnotatedElement source, SearchStrategy searchStrategy,
95-
AnnotationsProcessor<C, R> processor, @Nullable BiPredicate<C, Class<?>> classFilter) {
96-
97-
R result = process(context, source, searchStrategy, processor, classFilter);
77+
R result = process(context, source, searchStrategy, processor);
9878
return processor.finish(result);
9979
}
10080

10181
@Nullable
10282
private static <C, R> R process(C context, AnnotatedElement source,
103-
SearchStrategy searchStrategy, AnnotationsProcessor<C, R> processor,
104-
@Nullable BiPredicate<C, Class<?>> classFilter) {
83+
SearchStrategy searchStrategy, AnnotationsProcessor<C, R> processor) {
10584

10685
if (source instanceof Class) {
107-
return processClass(context, (Class<?>) source, searchStrategy, processor, classFilter);
86+
return processClass(context, (Class<?>) source, searchStrategy, processor);
10887
}
10988
if (source instanceof Method) {
110-
return processMethod(context, (Method) source, searchStrategy, processor, classFilter);
89+
return processMethod(context, (Method) source, searchStrategy, processor);
11190
}
112-
return processElement(context, source, processor, classFilter);
91+
return processElement(context, source, processor);
11392
}
11493

11594
@Nullable
11695
private static <C, R> R processClass(C context, Class<?> source,
117-
SearchStrategy searchStrategy, AnnotationsProcessor<C, R> processor,
118-
@Nullable BiPredicate<C, Class<?>> classFilter) {
96+
SearchStrategy searchStrategy, AnnotationsProcessor<C, R> processor) {
11997

12098
switch (searchStrategy) {
12199
case DIRECT:
122-
return processElement(context, source, processor, classFilter);
100+
return processElement(context, source, processor);
123101
case INHERITED_ANNOTATIONS:
124-
return processClassInheritedAnnotations(context, source, searchStrategy, processor, classFilter);
102+
return processClassInheritedAnnotations(context, source, searchStrategy, processor);
125103
case SUPERCLASS:
126-
return processClassHierarchy(context, source, processor, classFilter, false, false);
104+
return processClassHierarchy(context, source, processor, false, false);
127105
case TYPE_HIERARCHY:
128-
return processClassHierarchy(context, source, processor, classFilter, true, false);
106+
return processClassHierarchy(context, source, processor, true, false);
129107
case TYPE_HIERARCHY_AND_ENCLOSING_CLASSES:
130-
return processClassHierarchy(context, source, processor, classFilter, true, true);
108+
return processClassHierarchy(context, source, processor, true, true);
131109
}
132110
throw new IllegalStateException("Unsupported search strategy " + searchStrategy);
133111
}
134112

135113
@Nullable
136114
private static <C, R> R processClassInheritedAnnotations(C context, Class<?> source,
137-
SearchStrategy searchStrategy, AnnotationsProcessor<C, R> processor, @Nullable BiPredicate<C, Class<?>> classFilter) {
115+
SearchStrategy searchStrategy, AnnotationsProcessor<C, R> processor) {
138116

139117
try {
140118
if (isWithoutHierarchy(source, searchStrategy)) {
141-
return processElement(context, source, processor, classFilter);
119+
return processElement(context, source, processor);
142120
}
143121
Annotation[] relevant = null;
144122
int remaining = Integer.MAX_VALUE;
@@ -150,14 +128,7 @@ private static <C, R> R processClassInheritedAnnotations(C context, Class<?> sou
150128
if (result != null) {
151129
return result;
152130
}
153-
if (isFiltered(source, context, classFilter)) {
154-
// Skip the current level in the class hierarchy.
155-
source = source.getSuperclass();
156-
aggregateIndex++;
157-
continue;
158-
}
159-
Annotation[] declaredAnnotations =
160-
getDeclaredAnnotations(context, source, classFilter, true);
131+
Annotation[] declaredAnnotations = getDeclaredAnnotations(source, true);
161132
if (relevant == null && declaredAnnotations.length > 0) {
162133
relevant = root.getAnnotations();
163134
remaining = relevant.length;
@@ -195,17 +166,15 @@ private static <C, R> R processClassInheritedAnnotations(C context, Class<?> sou
195166

196167
@Nullable
197168
private static <C, R> R processClassHierarchy(C context, Class<?> source,
198-
AnnotationsProcessor<C, R> processor, @Nullable BiPredicate<C, Class<?>> classFilter,
199-
boolean includeInterfaces, boolean includeEnclosing) {
169+
AnnotationsProcessor<C, R> processor, boolean includeInterfaces, boolean includeEnclosing) {
200170

201171
return processClassHierarchy(context, new int[] {0}, source, processor,
202-
classFilter, includeInterfaces, includeEnclosing);
172+
includeInterfaces, includeEnclosing);
203173
}
204174

205175
@Nullable
206176
private static <C, R> R processClassHierarchy(C context, int[] aggregateIndex, Class<?> source,
207-
AnnotationsProcessor<C, R> processor, @Nullable BiPredicate<C, Class<?>> classFilter,
208-
boolean includeInterfaces, boolean includeEnclosing) {
177+
AnnotationsProcessor<C, R> processor, boolean includeInterfaces, boolean includeEnclosing) {
209178

210179
try {
211180
R result = processor.doWithAggregate(context, aggregateIndex[0]);
@@ -215,7 +184,7 @@ private static <C, R> R processClassHierarchy(C context, int[] aggregateIndex, C
215184
if (hasPlainJavaAnnotationsOnly(source)) {
216185
return null;
217186
}
218-
Annotation[] annotations = getDeclaredAnnotations(context, source, classFilter, false);
187+
Annotation[] annotations = getDeclaredAnnotations(source, false);
219188
result = processor.doWithAnnotations(context, aggregateIndex[0], source, annotations);
220189
if (result != null) {
221190
return result;
@@ -224,7 +193,7 @@ private static <C, R> R processClassHierarchy(C context, int[] aggregateIndex, C
224193
if (includeInterfaces) {
225194
for (Class<?> interfaceType : source.getInterfaces()) {
226195
R interfacesResult = processClassHierarchy(context, aggregateIndex,
227-
interfaceType, processor, classFilter, true, includeEnclosing);
196+
interfaceType, processor, true, includeEnclosing);
228197
if (interfacesResult != null) {
229198
return interfacesResult;
230199
}
@@ -233,7 +202,7 @@ private static <C, R> R processClassHierarchy(C context, int[] aggregateIndex, C
233202
Class<?> superclass = source.getSuperclass();
234203
if (superclass != Object.class && superclass != null) {
235204
R superclassResult = processClassHierarchy(context, aggregateIndex,
236-
superclass, processor, classFilter, includeInterfaces, includeEnclosing);
205+
superclass, processor, includeInterfaces, includeEnclosing);
237206
if (superclassResult != null) {
238207
return superclassResult;
239208
}
@@ -248,7 +217,7 @@ private static <C, R> R processClassHierarchy(C context, int[] aggregateIndex, C
248217
Class<?> enclosingClass = source.getEnclosingClass();
249218
if (enclosingClass != null) {
250219
R enclosingResult = processClassHierarchy(context, aggregateIndex,
251-
enclosingClass, processor, classFilter, includeInterfaces, true);
220+
enclosingClass, processor, includeInterfaces, true);
252221
if (enclosingResult != null) {
253222
return enclosingResult;
254223
}
@@ -267,32 +236,31 @@ private static <C, R> R processClassHierarchy(C context, int[] aggregateIndex, C
267236

268237
@Nullable
269238
private static <C, R> R processMethod(C context, Method source,
270-
SearchStrategy searchStrategy, AnnotationsProcessor<C, R> processor,
271-
@Nullable BiPredicate<C, Class<?>> classFilter) {
239+
SearchStrategy searchStrategy, AnnotationsProcessor<C, R> processor) {
272240

273241
switch (searchStrategy) {
274242
case DIRECT:
275243
case INHERITED_ANNOTATIONS:
276-
return processMethodInheritedAnnotations(context, source, processor, classFilter);
244+
return processMethodInheritedAnnotations(context, source, processor);
277245
case SUPERCLASS:
278246
return processMethodHierarchy(context, new int[] {0}, source.getDeclaringClass(),
279-
processor, classFilter, source, false);
247+
processor, source, false);
280248
case TYPE_HIERARCHY:
281249
case TYPE_HIERARCHY_AND_ENCLOSING_CLASSES:
282250
return processMethodHierarchy(context, new int[] {0}, source.getDeclaringClass(),
283-
processor, classFilter, source, true);
251+
processor, source, true);
284252
}
285253
throw new IllegalStateException("Unsupported search strategy " + searchStrategy);
286254
}
287255

288256
@Nullable
289257
private static <C, R> R processMethodInheritedAnnotations(C context, Method source,
290-
AnnotationsProcessor<C, R> processor, @Nullable BiPredicate<C, Class<?>> classFilter) {
258+
AnnotationsProcessor<C, R> processor) {
291259

292260
try {
293261
R result = processor.doWithAggregate(context, 0);
294262
return (result != null ? result :
295-
processMethodAnnotations(context, 0, source, processor, classFilter));
263+
processMethodAnnotations(context, 0, source, processor));
296264
}
297265
catch (Throwable ex) {
298266
AnnotationUtils.handleIntrospectionFailure(source, ex);
@@ -302,8 +270,7 @@ private static <C, R> R processMethodInheritedAnnotations(C context, Method sour
302270

303271
@Nullable
304272
private static <C, R> R processMethodHierarchy(C context, int[] aggregateIndex,
305-
Class<?> sourceClass, AnnotationsProcessor<C, R> processor,
306-
@Nullable BiPredicate<C, Class<?>> classFilter, Method rootMethod,
273+
Class<?> sourceClass, AnnotationsProcessor<C, R> processor, Method rootMethod,
307274
boolean includeInterfaces) {
308275

309276
try {
@@ -317,17 +284,17 @@ private static <C, R> R processMethodHierarchy(C context, int[] aggregateIndex,
317284
boolean calledProcessor = false;
318285
if (sourceClass == rootMethod.getDeclaringClass()) {
319286
result = processMethodAnnotations(context, aggregateIndex[0],
320-
rootMethod, processor, classFilter);
287+
rootMethod, processor);
321288
calledProcessor = true;
322289
if (result != null) {
323290
return result;
324291
}
325292
}
326293
else {
327-
for (Method candidateMethod : getBaseTypeMethods(context, sourceClass, classFilter)) {
294+
for (Method candidateMethod : getBaseTypeMethods(context, sourceClass)) {
328295
if (candidateMethod != null && isOverride(rootMethod, candidateMethod)) {
329296
result = processMethodAnnotations(context, aggregateIndex[0],
330-
candidateMethod, processor, classFilter);
297+
candidateMethod, processor);
331298
calledProcessor = true;
332299
if (result != null) {
333300
return result;
@@ -344,7 +311,7 @@ private static <C, R> R processMethodHierarchy(C context, int[] aggregateIndex,
344311
if (includeInterfaces) {
345312
for (Class<?> interfaceType : sourceClass.getInterfaces()) {
346313
R interfacesResult = processMethodHierarchy(context, aggregateIndex,
347-
interfaceType, processor, classFilter, rootMethod, true);
314+
interfaceType, processor, rootMethod, true);
348315
if (interfacesResult != null) {
349316
return interfacesResult;
350317
}
@@ -353,7 +320,7 @@ private static <C, R> R processMethodHierarchy(C context, int[] aggregateIndex,
353320
Class<?> superclass = sourceClass.getSuperclass();
354321
if (superclass != Object.class && superclass != null) {
355322
R superclassResult = processMethodHierarchy(context, aggregateIndex,
356-
superclass, processor, classFilter, rootMethod, includeInterfaces);
323+
superclass, processor, rootMethod, includeInterfaces);
357324
if (superclassResult != null) {
358325
return superclassResult;
359326
}
@@ -365,11 +332,8 @@ private static <C, R> R processMethodHierarchy(C context, int[] aggregateIndex,
365332
return null;
366333
}
367334

368-
private static <C> Method[] getBaseTypeMethods(
369-
C context, Class<?> baseType, @Nullable BiPredicate<C, Class<?>> classFilter) {
370-
371-
if (baseType == Object.class || hasPlainJavaAnnotationsOnly(baseType) ||
372-
isFiltered(baseType, context, classFilter)) {
335+
private static <C> Method[] getBaseTypeMethods(C context, Class<?> baseType) {
336+
if (baseType == Object.class || hasPlainJavaAnnotationsOnly(baseType)) {
373337
return NO_METHODS;
374338
}
375339

@@ -433,16 +397,16 @@ private static boolean hasSameGenericTypeParameters(
433397

434398
@Nullable
435399
private static <C, R> R processMethodAnnotations(C context, int aggregateIndex, Method source,
436-
AnnotationsProcessor<C, R> processor, @Nullable BiPredicate<C, Class<?>> classFilter) {
400+
AnnotationsProcessor<C, R> processor) {
437401

438-
Annotation[] annotations = getDeclaredAnnotations(context, source, classFilter, false);
402+
Annotation[] annotations = getDeclaredAnnotations(source, false);
439403
R result = processor.doWithAnnotations(context, aggregateIndex, source, annotations);
440404
if (result != null) {
441405
return result;
442406
}
443407
Method bridgedMethod = BridgeMethodResolver.findBridgedMethod(source);
444408
if (bridgedMethod != source) {
445-
Annotation[] bridgedAnnotations = getDeclaredAnnotations(context, bridgedMethod, classFilter, true);
409+
Annotation[] bridgedAnnotations = getDeclaredAnnotations(bridgedMethod, true);
446410
for (int i = 0; i < bridgedAnnotations.length; i++) {
447411
if (ObjectUtils.containsElement(annotations, bridgedAnnotations[i])) {
448412
bridgedAnnotations[i] = null;
@@ -455,31 +419,19 @@ private static <C, R> R processMethodAnnotations(C context, int aggregateIndex,
455419

456420
@Nullable
457421
private static <C, R> R processElement(C context, AnnotatedElement source,
458-
AnnotationsProcessor<C, R> processor, @Nullable BiPredicate<C, Class<?>> classFilter) {
422+
AnnotationsProcessor<C, R> processor) {
459423

460424
try {
461425
R result = processor.doWithAggregate(context, 0);
462426
return (result != null ? result : processor.doWithAnnotations(
463-
context, 0, source, getDeclaredAnnotations(context, source, classFilter, false)));
427+
context, 0, source, getDeclaredAnnotations(source, false)));
464428
}
465429
catch (Throwable ex) {
466430
AnnotationUtils.handleIntrospectionFailure(source, ex);
467431
}
468432
return null;
469433
}
470434

471-
private static <C, R> Annotation[] getDeclaredAnnotations(C context,
472-
AnnotatedElement source, @Nullable BiPredicate<C, Class<?>> classFilter, boolean copy) {
473-
474-
if (source instanceof Class && isFiltered((Class<?>) source, context, classFilter)) {
475-
return NO_ANNOTATIONS;
476-
}
477-
if (source instanceof Method && isFiltered(((Method) source).getDeclaringClass(), context, classFilter)) {
478-
return NO_ANNOTATIONS;
479-
}
480-
return getDeclaredAnnotations(source, copy);
481-
}
482-
483435
@SuppressWarnings("unchecked")
484436
@Nullable
485437
static <A extends Annotation> A getDeclaredAnnotation(AnnotatedElement source, Class<A> annotationType) {
@@ -525,12 +477,6 @@ static Annotation[] getDeclaredAnnotations(AnnotatedElement source, boolean defe
525477
return annotations.clone();
526478
}
527479

528-
private static <C> boolean isFiltered(
529-
Class<?> sourceClass, C context, @Nullable BiPredicate<C, Class<?>> classFilter) {
530-
531-
return (classFilter != null && classFilter.test(context, sourceClass));
532-
}
533-
534480
private static boolean isIgnorable(Class<?> annotationType) {
535481
return AnnotationFilter.PLAIN.matches(annotationType);
536482
}

spring-core/src/test/java/org/springframework/core/annotation/AnnotationsScannerTests.java

Lines changed: 0 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -128,51 +128,6 @@ void inheritedAnnotationsStrategyOnClassWhenHasAnnotationOnBothClassesIncudesOnl
128128
assertThat(scan(source, SearchStrategy.INHERITED_ANNOTATIONS)).containsExactly("0:TestInheritedAnnotation2");
129129
}
130130

131-
@Test
132-
void inheritedAnnotationsStrategyOnClassWithAllClassesFilteredOut() {
133-
List<String> annotationsFound = new ArrayList<>();
134-
String scanResult = AnnotationsScanner.scan(this, WithSingleSuperclass.class,
135-
SearchStrategy.INHERITED_ANNOTATIONS,
136-
(context, aggregateIndex, source, annotations) -> {
137-
trackIndexedAnnotations(aggregateIndex, annotations, annotationsFound);
138-
return null; // continue searching
139-
},
140-
(context, clazz) -> true // filter out all classes
141-
);
142-
assertThat(annotationsFound).isEmpty();
143-
assertThat(scanResult).isNull();
144-
}
145-
146-
@Test
147-
void inheritedAnnotationsStrategyOnClassWithSourceClassFilteredOut() {
148-
List<String> annotationsFound = new ArrayList<>();
149-
String scanResult = AnnotationsScanner.scan(this, WithSingleSuperclass.class,
150-
SearchStrategy.INHERITED_ANNOTATIONS,
151-
(context, aggregateIndex, source, annotations) -> {
152-
trackIndexedAnnotations(aggregateIndex, annotations, annotationsFound);
153-
return null; // continue searching
154-
},
155-
(context, clazz) -> clazz == WithSingleSuperclass.class
156-
);
157-
assertThat(annotationsFound).containsExactly(/* "0:TestAnnotation1", */ "1:TestInheritedAnnotation2");
158-
assertThat(scanResult).isNull();
159-
}
160-
161-
@Test
162-
void inheritedAnnotationsStrategyInClassHierarchyWithSuperSuperclassFilteredOut() {
163-
List<String> annotationsFound = new ArrayList<>();
164-
String scanResult = AnnotationsScanner.scan(this, WithHierarchy.class,
165-
SearchStrategy.INHERITED_ANNOTATIONS,
166-
(context, aggregateIndex, source, annotations) -> {
167-
trackIndexedAnnotations(aggregateIndex, annotations, annotationsFound);
168-
return null; // continue searching
169-
},
170-
(context, clazz) -> clazz == HierarchySuperSuperclass.class
171-
);
172-
assertThat(annotationsFound).containsExactly("0:TestAnnotation1", "1:TestInheritedAnnotation2");
173-
assertThat(scanResult).isNull();
174-
}
175-
176131
@Test
177132
void superclassStrategyOnClassWhenNotAnnotatedScansNone() {
178133
Class<?> source = WithNoAnnotations.class;

0 commit comments

Comments
 (0)