Favor local @ComponentScan annotations over meta-annotations
Work performed in conjunction with gh-30941 resulted in a regression. Specifically, prior to Spring Framework 6.1 a locally declared @ComponentScan annotation took precedence over @ComponentScan meta-annotations, which allowed "local" configuration to override "meta-present" configuration. This commit modifies the @ComponentScan search algorithm so that locally declared @ComponentScan annotations are once again favored over @ComponentScan meta-annotations (and, indirectly, composed annotations). See gh-30941 Closes gh-31704
This commit is contained in:
@@ -21,6 +21,7 @@ import java.util.Comparator;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
@@ -181,6 +182,7 @@ public interface AnnotatedTypeMetadata {
|
||||
* or an empty set if none were found
|
||||
* @since 6.1
|
||||
* @see #getMergedRepeatableAnnotationAttributes(Class, Class, boolean, boolean)
|
||||
* @see #getMergedRepeatableAnnotationAttributes(Class, Class, Predicate, boolean, boolean)
|
||||
*/
|
||||
default Set<AnnotationAttributes> getMergedRepeatableAnnotationAttributes(
|
||||
Class<? extends Annotation> annotationType, Class<? extends Annotation> containerType,
|
||||
@@ -216,12 +218,58 @@ public interface AnnotatedTypeMetadata {
|
||||
* or an empty set if none were found
|
||||
* @since 6.1
|
||||
* @see #getMergedRepeatableAnnotationAttributes(Class, Class, boolean)
|
||||
* @see #getMergedRepeatableAnnotationAttributes(Class, Class, Predicate, boolean, boolean)
|
||||
*/
|
||||
default Set<AnnotationAttributes> getMergedRepeatableAnnotationAttributes(
|
||||
Class<? extends Annotation> annotationType, Class<? extends Annotation> containerType,
|
||||
boolean classValuesAsString, boolean sortByReversedMetaDistance) {
|
||||
|
||||
return getMergedRepeatableAnnotationAttributes(annotationType, containerType,
|
||||
mergedAnnotation -> true, classValuesAsString, sortByReversedMetaDistance);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve all <em>repeatable annotations</em> of the given type within the
|
||||
* annotation hierarchy <em>above</em> the underlying element (as direct
|
||||
* annotation or meta-annotation); and for each annotation found, merge that
|
||||
* annotation's attributes with <em>matching</em> attributes from annotations
|
||||
* in lower levels of the annotation hierarchy and store the results in an
|
||||
* instance of {@link AnnotationAttributes}.
|
||||
* <p>{@link org.springframework.core.annotation.AliasFor @AliasFor} semantics
|
||||
* are fully supported, both within a single annotation and within annotation
|
||||
* hierarchies.
|
||||
* <p>The supplied {@link Predicate} will be used to filter the results. For
|
||||
* example, supply {@code mergedAnnotation -> true} to include all annotations
|
||||
* in the results; supply {@code MergedAnnotation::isDirectlyPresent} to limit
|
||||
* the results to directly declared annotations, etc.
|
||||
* <p>If the {@code sortByReversedMetaDistance} flag is set to {@code true},
|
||||
* the results will be sorted in {@link Comparator#reversed() reversed} order
|
||||
* based on each annotation's {@linkplain MergedAnnotation#getDistance()
|
||||
* meta distance}, which effectively orders meta-annotations before annotations
|
||||
* that are declared directly on the underlying element.
|
||||
* @param annotationType the annotation type to find
|
||||
* @param containerType the type of the container that holds the annotations
|
||||
* @param predicate a {@code Predicate} to apply to each {@code MergedAnnotation}
|
||||
* to determine if it should be included in the results
|
||||
* @param classValuesAsString whether to convert class references to {@code String}
|
||||
* class names for exposure as values in the returned {@code AnnotationAttributes},
|
||||
* instead of {@code Class} references which might potentially have to be loaded
|
||||
* first
|
||||
* @param sortByReversedMetaDistance {@code true} if the results should be
|
||||
* sorted in reversed order based on each annotation's meta distance
|
||||
* @return the set of all merged repeatable {@code AnnotationAttributes} found,
|
||||
* or an empty set if none were found
|
||||
* @since 6.1.2
|
||||
* @see #getMergedRepeatableAnnotationAttributes(Class, Class, boolean)
|
||||
* @see #getMergedRepeatableAnnotationAttributes(Class, Class, boolean, boolean)
|
||||
*/
|
||||
default Set<AnnotationAttributes> getMergedRepeatableAnnotationAttributes(
|
||||
Class<? extends Annotation> annotationType, Class<? extends Annotation> containerType,
|
||||
Predicate<MergedAnnotation<? extends Annotation>> predicate, boolean classValuesAsString,
|
||||
boolean sortByReversedMetaDistance) {
|
||||
|
||||
Stream<MergedAnnotation<Annotation>> stream = getAnnotations().stream()
|
||||
.filter(predicate)
|
||||
.filter(MergedAnnotationPredicates.typeIn(containerType, annotationType));
|
||||
|
||||
if (sortByReversedMetaDistance) {
|
||||
|
||||
Reference in New Issue
Block a user