Ensure direct @PropertySource annotations override meta-annotations

Prior to this commit, there was an issue with the semantics of property
source overrides. Specifically, a @PropertySource annotation present as
a meta-annotation on a @Configuration class was registered with higher
precedence than a @PropertySource annotation declared closer to (or
directly on) the @Configuration class. Consequently, there was no way
for a "local" @PropertySource annotation to override properties
registered via @PropertySource as a meta-annotation.

This commit addresses this issue by introducing a new overloaded
getMergedRepeatableAnnotationAttributes() variant in
AnnotatedTypeMetadata that allows the caller to supply a
sortByReversedMetaDistance flag. When set to `true`, the annotation
search results will be sorted in reversed order based on each
annotation's meta distance, which effectively orders meta-annotations
before annotations that are declared directly on the underlying element.

ConfigurationClassParser and AnnotationConfigUtils have been updated to
use this new repeatable annotation search method for @PropertySource.

Closes gh-31074
This commit is contained in:
Sam Brannen
2023-08-18 16:23:35 +02:00
parent 285c92bb03
commit 74130d007b
5 changed files with 87 additions and 4 deletions

View File

@@ -286,4 +286,11 @@ public abstract class AnnotationConfigUtils {
return metadata.getMergedRepeatableAnnotationAttributes(annotationType, containerType, false);
}
static Set<AnnotationAttributes> attributesForRepeatable(AnnotationMetadata metadata,
Class<? extends Annotation> annotationType, Class<? extends Annotation> containerType,
boolean sortByReversedMetaDistance) {
return metadata.getMergedRepeatableAnnotationAttributes(annotationType, containerType, false, sortByReversedMetaDistance);
}
}

View File

@@ -268,7 +268,7 @@ class ConfigurationClassParser {
// Process any @PropertySource annotations
for (AnnotationAttributes propertySource : AnnotationConfigUtils.attributesForRepeatable(
sourceClass.getMetadata(), org.springframework.context.annotation.PropertySource.class,
PropertySources.class)) {
PropertySources.class, true)) {
if (this.propertySourceRegistry != null) {
this.propertySourceRegistry.processPropertySource(propertySource);
}