diff --git a/spring-core/src/main/java/org/springframework/core/annotation/AnnotationsScanner.java b/spring-core/src/main/java/org/springframework/core/annotation/AnnotationsScanner.java index 3b5eaaacc1..61fea06852 100644 --- a/spring-core/src/main/java/org/springframework/core/annotation/AnnotationsScanner.java +++ b/spring-core/src/main/java/org/springframework/core/annotation/AnnotationsScanner.java @@ -107,7 +107,6 @@ abstract class AnnotationsScanner { case INHERITED_ANNOTATIONS -> processClassInheritedAnnotations(context, source, searchStrategy, processor); case SUPERCLASS -> processClassHierarchy(context, source, processor, false, Search.never); case TYPE_HIERARCHY -> processClassHierarchy(context, source, processor, true, searchEnclosingClass); - case TYPE_HIERARCHY_AND_ENCLOSING_CLASSES -> processClassHierarchy(context, source, processor, true, Search.always); }; } @@ -246,8 +245,7 @@ abstract class AnnotationsScanner { case DIRECT, INHERITED_ANNOTATIONS -> processMethodInheritedAnnotations(context, source, processor); case SUPERCLASS -> processMethodHierarchy(context, new int[]{0}, source.getDeclaringClass(), processor, source, false); - case TYPE_HIERARCHY, TYPE_HIERARCHY_AND_ENCLOSING_CLASSES -> processMethodHierarchy(context, new int[]{0}, - source.getDeclaringClass(), + case TYPE_HIERARCHY -> processMethodHierarchy(context, new int[]{0}, source.getDeclaringClass(), processor, source, true); }; } diff --git a/spring-core/src/main/java/org/springframework/core/annotation/MergedAnnotations.java b/spring-core/src/main/java/org/springframework/core/annotation/MergedAnnotations.java index be60a79d10..5a26e0c84a 100644 --- a/spring-core/src/main/java/org/springframework/core/annotation/MergedAnnotations.java +++ b/spring-core/src/main/java/org/springframework/core/annotation/MergedAnnotations.java @@ -356,10 +356,7 @@ public interface MergedAnnotations extends Iterable static MergedAnnotations from(AnnotatedElement element, SearchStrategy searchStrategy, RepeatableContainers repeatableContainers, AnnotationFilter annotationFilter) { - Predicate> searchEnclosingClass = - (searchStrategy == SearchStrategy.TYPE_HIERARCHY_AND_ENCLOSING_CLASSES ? - Search.always : Search.never); - return from(element, searchStrategy, searchEnclosingClass, repeatableContainers, annotationFilter); + return from(element, searchStrategy, Search.never, repeatableContainers, annotationFilter); } private static MergedAnnotations from(AnnotatedElement element, SearchStrategy searchStrategy, @@ -668,28 +665,7 @@ public interface MergedAnnotations extends Iterable *

Superclass and enclosing class annotations do not need to be * meta-annotated with {@link Inherited @Inherited}. */ - TYPE_HIERARCHY, - - /** - * Perform a full search of the entire type hierarchy on the source - * and any enclosing classes. - *

This strategy is similar to {@link #TYPE_HIERARCHY} except that - * {@linkplain Class#getEnclosingClass() enclosing classes} are also - * searched. - *

Superclass and enclosing class annotations do not need to be - * meta-annotated with {@link Inherited @Inherited}. - *

When searching a {@link Method} source, this strategy is identical - * to {@link #TYPE_HIERARCHY}. - *

WARNING: This strategy searches recursively for - * annotations on the enclosing class for any source type, regardless - * whether the source type is an inner class, a {@code static} - * nested class, or a nested interface. Thus, it may find more annotations - * than you would expect. - * @deprecated as of Spring Framework 6.0 M3, for potential removal or - * replacement before 6.0 GA - */ - @Deprecated - TYPE_HIERARCHY_AND_ENCLOSING_CLASSES + TYPE_HIERARCHY } diff --git a/spring-core/src/test/java/org/springframework/core/annotation/AnnotationsScannerTests.java b/spring-core/src/test/java/org/springframework/core/annotation/AnnotationsScannerTests.java index fa6eb99a1a..bb8de3af44 100644 --- a/spring-core/src/test/java/org/springframework/core/annotation/AnnotationsScannerTests.java +++ b/spring-core/src/test/java/org/springframework/core/annotation/AnnotationsScannerTests.java @@ -26,6 +26,7 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.Objects; +import java.util.function.Predicate; import java.util.stream.Stream; import org.junit.jupiter.api.Test; @@ -33,6 +34,7 @@ import org.junit.jupiter.api.Test; import org.springframework.core.annotation.MergedAnnotations.Search; import org.springframework.core.annotation.MergedAnnotations.SearchStrategy; import org.springframework.lang.Nullable; +import org.springframework.util.ClassUtils; import org.springframework.util.ReflectionUtils; import static org.assertj.core.api.Assertions.assertThat; @@ -422,29 +424,34 @@ class AnnotationsScannerTests { } @Test - @SuppressWarnings("deprecation") - void typeHierarchyWithEnclosedStrategyOnEnclosedStaticClassScansAnnotations() { + void typeHierarchyStrategyWithEnclosingClassPredicatesOnEnclosedStaticClassScansAnnotations() { Class source = AnnotationEnclosingClassSample.EnclosedStatic.EnclosedStaticStatic.class; - assertThat(scan(source, SearchStrategy.TYPE_HIERARCHY_AND_ENCLOSING_CLASSES)) + assertThat(scan(source, SearchStrategy.TYPE_HIERARCHY, ClassUtils::isInnerClass)) + .containsExactly("0:EnclosedThree"); + assertThat(scan(source, SearchStrategy.TYPE_HIERARCHY, Search.always).toList()) + .isEqualTo(scan(source, SearchStrategy.TYPE_HIERARCHY, ClassUtils::isStaticClass).toList()) .containsExactly("0:EnclosedThree", "1:EnclosedTwo", "2:EnclosedOne"); } @Test - @SuppressWarnings("deprecation") - void typeHierarchyWithEnclosedStrategyOnEnclosedInnerClassScansAnnotations() { + void typeHierarchyStrategyWithEnclosingClassPredicatesOnEnclosedInnerClassScansAnnotations() { Class source = AnnotationEnclosingClassSample.EnclosedInner.EnclosedInnerInner.class; - assertThat(scan(source, SearchStrategy.TYPE_HIERARCHY_AND_ENCLOSING_CLASSES)) + assertThat(scan(source, SearchStrategy.TYPE_HIERARCHY, ClassUtils::isStaticClass)) + .containsExactly("0:EnclosedThree"); + assertThat(scan(source, SearchStrategy.TYPE_HIERARCHY, Search.always).toList()) + .isEqualTo(scan(source, SearchStrategy.TYPE_HIERARCHY, ClassUtils::isInnerClass).toList()) .containsExactly("0:EnclosedThree", "1:EnclosedTwo", "2:EnclosedOne"); } @Test - @SuppressWarnings("deprecation") - void typeHierarchyWithEnclosedStrategyOnMethodHierarchyUsesTypeHierarchyScan() { + void typeHierarchyStrategyWithEnclosingClassPredicatesOnMethodHierarchyUsesTypeHierarchyScan() { Method source = methodFrom(WithHierarchy.class); - assertThat(scan(source, SearchStrategy.TYPE_HIERARCHY_AND_ENCLOSING_CLASSES)).containsExactly( - "0:TestAnnotation1", "1:TestAnnotation5", "1:TestInheritedAnnotation5", - "2:TestAnnotation6", "3:TestAnnotation2", "3:TestInheritedAnnotation2", - "4:TestAnnotation3", "5:TestAnnotation4"); + assertThat(scan(source, SearchStrategy.TYPE_HIERARCHY, Search.always).toList()) + .isEqualTo(scan(source, SearchStrategy.TYPE_HIERARCHY, ClassUtils::isInnerClass).toList()) + .containsExactly( + "0:TestAnnotation1", "1:TestAnnotation5", "1:TestInheritedAnnotation5", + "2:TestAnnotation6", "3:TestAnnotation2", "3:TestInheritedAnnotation2", + "4:TestAnnotation3", "5:TestAnnotation4"); } @Test @@ -509,8 +516,14 @@ class AnnotationsScannerTests { } private Stream scan(AnnotatedElement element, SearchStrategy searchStrategy) { + return scan(element, searchStrategy, Search.never); + } + + private Stream scan(AnnotatedElement element, SearchStrategy searchStrategy, + Predicate> searchEnclosingClass) { + List results = new ArrayList<>(); - scan(this, element, searchStrategy, + scan(this, element, searchStrategy, searchEnclosingClass, (criteria, aggregateIndex, source, annotations) -> { trackIndexedAnnotations(aggregateIndex, annotations, results); return null; // continue searching @@ -521,7 +534,13 @@ class AnnotationsScannerTests { private static R scan(C context, AnnotatedElement source, SearchStrategy searchStrategy, AnnotationsProcessor processor) { - return AnnotationsScanner.scan(context, source, searchStrategy, Search.never, processor); + return scan(context, source, searchStrategy, Search.never, processor); + } + + private static R scan(C context, AnnotatedElement source, SearchStrategy searchStrategy, + Predicate> searchEnclosingClass, AnnotationsProcessor processor) { + + return AnnotationsScanner.scan(context, source, searchStrategy, searchEnclosingClass, processor); } private void trackIndexedAnnotations(int aggregateIndex, Annotation[] annotations, List results) { diff --git a/spring-core/src/test/java/org/springframework/core/annotation/MergedAnnotationsTests.java b/spring-core/src/test/java/org/springframework/core/annotation/MergedAnnotationsTests.java index 143312b0b6..cb3a3b7618 100644 --- a/spring-core/src/test/java/org/springframework/core/annotation/MergedAnnotationsTests.java +++ b/spring-core/src/test/java/org/springframework/core/annotation/MergedAnnotationsTests.java @@ -843,22 +843,6 @@ class MergedAnnotationsTests { Transactional.class)).hasSize(1); } - @Test - @SuppressWarnings("deprecation") - void streamTypeHierarchyAndEnclosingClassesFromNonAnnotatedInnerClassWithAnnotatedEnclosingClass() { - Stream> classes = MergedAnnotations.from(AnnotatedClass.NonAnnotatedInnerClass.class, - SearchStrategy.TYPE_HIERARCHY_AND_ENCLOSING_CLASSES).stream().map(MergedAnnotation::getType); - assertThat(classes).containsExactly(Component.class, Indexed.class); - } - - @Test - @SuppressWarnings("deprecation") - void streamTypeHierarchyAndEnclosingClassesFromNonAnnotatedStaticNestedClassWithAnnotatedEnclosingClass() { - Stream> classes = MergedAnnotations.from(AnnotatedClass.NonAnnotatedStaticNestedClass.class, - SearchStrategy.TYPE_HIERARCHY_AND_ENCLOSING_CLASSES).stream().map(MergedAnnotation::getType); - assertThat(classes).containsExactly(Component.class, Indexed.class); - } - @Test @SuppressWarnings("deprecation") void getFromMethodWithMethodAnnotationOnLeaf() throws Exception {