From fde7116ae441c72dfbc66606ab1a3de7fc84a6f6 Mon Sep 17 00:00:00 2001 From: Juergen Hoeller Date: Wed, 16 Oct 2024 17:17:22 +0200 Subject: [PATCH] Consistently skip processing of plain Java annotations Closes gh-33580 --- ...ierAnnotationAutowireCandidateResolver.java | 18 +++++++++++++++++- .../core/annotation/AnnotationsScanner.java | 17 +++++++---------- 2 files changed, 24 insertions(+), 11 deletions(-) diff --git a/spring-beans/src/main/java/org/springframework/beans/factory/annotation/QualifierAnnotationAutowireCandidateResolver.java b/spring-beans/src/main/java/org/springframework/beans/factory/annotation/QualifierAnnotationAutowireCandidateResolver.java index cf552f996e00..47d5ad1c8d87 100644 --- a/spring-beans/src/main/java/org/springframework/beans/factory/annotation/QualifierAnnotationAutowireCandidateResolver.java +++ b/spring-beans/src/main/java/org/springframework/beans/factory/annotation/QualifierAnnotationAutowireCandidateResolver.java @@ -180,6 +180,9 @@ protected boolean checkQualifiers(BeanDefinitionHolder bdHolder, Annotation[] an SimpleTypeConverter typeConverter = new SimpleTypeConverter(); for (Annotation annotation : annotationsToSearch) { Class type = annotation.annotationType(); + if (isPlainJavaAnnotation(type)) { + continue; + } boolean checkMeta = true; boolean fallbackToMeta = false; if (isQualifier(type)) { @@ -194,6 +197,9 @@ protected boolean checkQualifiers(BeanDefinitionHolder bdHolder, Annotation[] an boolean foundMeta = false; for (Annotation metaAnn : type.getAnnotations()) { Class metaType = metaAnn.annotationType(); + if (isPlainJavaAnnotation(metaType)) { + continue; + } if (isQualifier(metaType)) { foundMeta = true; // Only accept fallback match if @Qualifier annotation has a value... @@ -213,7 +219,17 @@ protected boolean checkQualifiers(BeanDefinitionHolder bdHolder, Annotation[] an } /** - * Checks whether the given annotation type is a recognized qualifier type. + * Check whether the given annotation type is a plain "java." annotation, + * typically from {@code java.lang.annotation}. + *

Aligned with + * {@code org.springframework.core.annotation.AnnotationsScanner#hasPlainJavaAnnotationsOnly}. + */ + private boolean isPlainJavaAnnotation(Class annotationType) { + return annotationType.getName().startsWith("java."); + } + + /** + * Check whether the given annotation type is a recognized qualifier type. */ protected boolean isQualifier(Class annotationType) { for (Class qualifierType : this.qualifierTypes) { 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 5bd7168f96a1..a3d08f369bbe 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 @@ -103,7 +103,7 @@ private static R processClass(C context, Class source, SearchStrategy return switch (searchStrategy) { case DIRECT -> processElement(context, source, processor); - case INHERITED_ANNOTATIONS -> processClassInheritedAnnotations(context, source, searchStrategy, processor); + case INHERITED_ANNOTATIONS -> processClassInheritedAnnotations(context, source, processor); case SUPERCLASS -> processClassHierarchy(context, source, processor, false, Search.never); case TYPE_HIERARCHY -> processClassHierarchy(context, source, processor, true, searchEnclosingClass); }; @@ -111,18 +111,17 @@ private static R processClass(C context, Class source, SearchStrategy @Nullable private static R processClassInheritedAnnotations(C context, Class source, - SearchStrategy searchStrategy, AnnotationsProcessor processor) { + AnnotationsProcessor processor) { try { - if (isWithoutHierarchy(source, searchStrategy, Search.never)) { + if (isWithoutHierarchy(source, Search.never)) { return processElement(context, source, processor); } Annotation[] relevant = null; int remaining = Integer.MAX_VALUE; int aggregateIndex = 0; Class root = source; - while (source != null && source != Object.class && remaining > 0 && - !hasPlainJavaAnnotationsOnly(source)) { + while (source != null && source != Object.class && remaining > 0 && !hasPlainJavaAnnotationsOnly(source)) { R result = processor.doWithAggregate(context, aggregateIndex); if (result != null) { return result; @@ -483,7 +482,7 @@ static boolean isKnownEmpty(AnnotatedElement source, SearchStrategy searchStrate if (hasPlainJavaAnnotationsOnly(source)) { return true; } - if (searchStrategy == SearchStrategy.DIRECT || isWithoutHierarchy(source, searchStrategy, searchEnclosingClass)) { + if (searchStrategy == SearchStrategy.DIRECT || isWithoutHierarchy(source, searchEnclosingClass)) { if (source instanceof Method method && method.isBridge()) { return false; } @@ -508,9 +507,7 @@ static boolean hasPlainJavaAnnotationsOnly(Class type) { return (type.getName().startsWith("java.") || type == Ordered.class); } - private static boolean isWithoutHierarchy(AnnotatedElement source, SearchStrategy searchStrategy, - Predicate> searchEnclosingClass) { - + private static boolean isWithoutHierarchy(AnnotatedElement source, Predicate> searchEnclosingClass) { if (source == Object.class) { return true; } @@ -522,7 +519,7 @@ private static boolean isWithoutHierarchy(AnnotatedElement source, SearchStrateg } if (source instanceof Method sourceMethod) { return (Modifier.isPrivate(sourceMethod.getModifiers()) || - isWithoutHierarchy(sourceMethod.getDeclaringClass(), searchStrategy, searchEnclosingClass)); + isWithoutHierarchy(sourceMethod.getDeclaringClass(), searchEnclosingClass)); } return true; }