Skip to content

Commit de3c115

Browse files
committed
Fix bug in TYPE_HIERARCHY_AND_ENCLOSING_CLASSES strategy
Prior to this commit, the new `TYPE_HIERARCHY_AND_ENCLOSING_CLASSES` annotation search strategy failed to find annotations on enclosing classes if the source class was a nested class that itself had no annotations present. This commit fixes this by adding special logic to AnnotationsScanner's isWithoutHierarchy() method to properly support nested classes. Closes gh-23378
1 parent b03dd47 commit de3c115

File tree

2 files changed

+35
-7
lines changed

2 files changed

+35
-7
lines changed

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

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@
3939
* {@link AnnotatedElement}.
4040
*
4141
* @author Phillip Webb
42+
* @author Sam Brannen
4243
* @since 5.2
4344
* @see AnnotationsProcessor
4445
*/
@@ -121,7 +122,7 @@ private static <C, R> R processClass(C context, Class<?> source,
121122
case DIRECT:
122123
return processElement(context, source, processor, classFilter);
123124
case INHERITED_ANNOTATIONS:
124-
return processClassInheritedAnnotations(context, source, processor, classFilter);
125+
return processClassInheritedAnnotations(context, source, searchStrategy, processor, classFilter);
125126
case SUPERCLASS:
126127
return processClassHierarchy(context, source, processor, classFilter, false, false);
127128
case EXHAUSTIVE:
@@ -135,9 +136,9 @@ private static <C, R> R processClass(C context, Class<?> source,
135136

136137
@Nullable
137138
private static <C, R> R processClassInheritedAnnotations(C context, Class<?> source,
138-
AnnotationsProcessor<C, R> processor, @Nullable BiPredicate<C, Class<?>> classFilter) {
139+
SearchStrategy searchStrategy, AnnotationsProcessor<C, R> processor, @Nullable BiPredicate<C, Class<?>> classFilter) {
139140

140-
if (isWithoutHierarchy(source)) {
141+
if (isWithoutHierarchy(source, searchStrategy)) {
141142
return processElement(context, source, processor, classFilter);
142143
}
143144
Annotation[] relevant = null;
@@ -505,7 +506,7 @@ static boolean isKnownEmpty(AnnotatedElement source, SearchStrategy searchStrate
505506
if (hasPlainJavaAnnotationsOnly(source)) {
506507
return true;
507508
}
508-
if (searchStrategy == SearchStrategy.DIRECT || isWithoutHierarchy(source)) {
509+
if (searchStrategy == SearchStrategy.DIRECT || isWithoutHierarchy(source, searchStrategy)) {
509510
if (source instanceof Method && ((Method) source).isBridge()) {
510511
return false;
511512
}
@@ -530,19 +531,21 @@ static boolean hasPlainJavaAnnotationsOnly(Class<?> type) {
530531
return (type.getName().startsWith("java.") || type == Ordered.class);
531532
}
532533

533-
private static boolean isWithoutHierarchy(AnnotatedElement source) {
534+
private static boolean isWithoutHierarchy(AnnotatedElement source, SearchStrategy searchStrategy) {
534535
if (source == Object.class) {
535536
return true;
536537
}
537538
if (source instanceof Class) {
538539
Class<?> sourceClass = (Class<?>) source;
539-
return (sourceClass.getSuperclass() == Object.class &&
540+
boolean noSuperTypes = (sourceClass.getSuperclass() == Object.class &&
540541
sourceClass.getInterfaces().length == 0);
542+
return (searchStrategy == SearchStrategy.TYPE_HIERARCHY_AND_ENCLOSING_CLASSES ? noSuperTypes &&
543+
sourceClass.getEnclosingClass() == null : noSuperTypes);
541544
}
542545
if (source instanceof Method) {
543546
Method sourceMethod = (Method) source;
544547
return (Modifier.isPrivate(sourceMethod.getModifiers()) ||
545-
isWithoutHierarchy(sourceMethod.getDeclaringClass()));
548+
isWithoutHierarchy(sourceMethod.getDeclaringClass(), searchStrategy));
546549
}
547550
return true;
548551
}

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

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -692,6 +692,19 @@ public void streamTypeHierarchyFromClassWithInterface() throws Exception {
692692
Transactional.class)).hasSize(1);
693693
}
694694

695+
@Test
696+
public void streamTypeHierarchyAndEnclosingClassesFromNonAnnotatedInnerClassWithAnnotatedEnclosingClass() {
697+
Stream<Class<?>> classes = MergedAnnotations.from(AnnotatedClass.NonAnnotatedInnerClass.class,
698+
SearchStrategy.TYPE_HIERARCHY_AND_ENCLOSING_CLASSES).stream().map(MergedAnnotation::getType);
699+
assertThat(classes).containsExactly(Component.class, Indexed.class);
700+
}
701+
702+
@Test
703+
public void streamTypeHierarchyAndEnclosingClassesFromNonAnnotatedStaticNestedClassWithAnnotatedEnclosingClass() {
704+
Stream<Class<?>> classes = MergedAnnotations.from(AnnotatedClass.NonAnnotatedStaticNestedClass.class,
705+
SearchStrategy.TYPE_HIERARCHY_AND_ENCLOSING_CLASSES).stream().map(MergedAnnotation::getType);
706+
assertThat(classes).containsExactly(Component.class, Indexed.class);
707+
}
695708
@Test
696709
public void getFromMethodWithMethodAnnotationOnLeaf() throws Exception {
697710
Method method = Leaf.class.getMethod("annotatedOnLeaf");
@@ -2112,6 +2125,16 @@ public void asAnnotationAttributesReturnsPopulatedAnnotationAttributes() {
21122125
static class NonAnnotatedClass {
21132126
}
21142127

2128+
@Component
2129+
static class AnnotatedClass {
2130+
2131+
class NonAnnotatedInnerClass {
2132+
}
2133+
2134+
static class NonAnnotatedStaticNestedClass {
2135+
}
2136+
}
2137+
21152138
static interface NonAnnotatedInterface {
21162139
}
21172140

@@ -2839,6 +2862,7 @@ public interface InterfaceWithGenericAnnotatedMethod<T> {
28392862
public static class ImplementsInterfaceWithGenericAnnotatedMethod
28402863
implements InterfaceWithGenericAnnotatedMethod<String> {
28412864

2865+
@Override
28422866
public void foo(String t) {
28432867
}
28442868
}
@@ -2852,6 +2876,7 @@ public static abstract class BaseClassWithGenericAnnotatedMethod<T> {
28522876
public static class ExtendsBaseClassWithGenericAnnotatedMethod
28532877
extends BaseClassWithGenericAnnotatedMethod<String> {
28542878

2879+
@Override
28552880
public void foo(String t) {
28562881
}
28572882
}

0 commit comments

Comments
 (0)