Skip to content

Commit 197f659

Browse files
committed
Simplify annotation attribute override algorithm
Issue: SPR-11513
1 parent c809324 commit 197f659

File tree

2 files changed

+30
-41
lines changed

2 files changed

+30
-41
lines changed

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

Lines changed: 13 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,6 @@
3131
import org.springframework.util.Assert;
3232
import org.springframework.util.LinkedMultiValueMap;
3333
import org.springframework.util.MultiValueMap;
34-
import org.springframework.util.ReflectionUtils;
3534
import org.springframework.util.StringUtils;
3635

3736
/**
@@ -941,35 +940,25 @@ public void postProcess(AnnotatedElement element, Annotation annotation, Annotat
941940
targetAnnotationType);
942941

943942
// Explicit annotation attribute override declared via @AliasFor
944-
if (StringUtils.hasText(aliasedAttributeName)) {
945-
if (attributes.containsKey(aliasedAttributeName)) {
946-
Object value = AnnotationUtils.getValue(annotation, attributeName);
947-
attributes.put(aliasedAttributeName, AnnotationUtils.adaptValue(element, value,
948-
this.classValuesAsString, this.nestedAnnotationsAsMap));
949-
}
943+
if (StringUtils.hasText(aliasedAttributeName) && attributes.containsKey(aliasedAttributeName)) {
944+
overrideAttribute(element, annotation, attributes, attributeName, aliasedAttributeName);
950945
}
951946
// Implicit annotation attribute override based on convention
952947
else if (!AnnotationUtils.VALUE.equals(attributeName) && attributes.containsKey(attributeName)) {
953-
Object value = AnnotationUtils.getValue(annotation, attributeName);
954-
Object adaptedValue = AnnotationUtils.adaptValue(element, value, this.classValuesAsString,
955-
this.nestedAnnotationsAsMap);
956-
attributes.put(attributeName, adaptedValue);
957-
958-
// If an aliased attribute defined by @AliasFor semantics does not
959-
// already have an explicit value, ensure that the aliased attribute
960-
// is also present in the map with a value identical to its mirror
961-
// alias.
962-
Method attributeMethodInTarget = ReflectionUtils.findMethod(targetAnnotationType, attributeName);
963-
if (attributeMethodInTarget != null) {
964-
String aliasedAttributeNameInTarget = AnnotationUtils.getAliasedAttributeName(
965-
attributeMethodInTarget, null);
966-
if (aliasedAttributeNameInTarget != null) {
967-
attributes.putIfAbsent(aliasedAttributeNameInTarget, adaptedValue);
968-
}
969-
}
948+
overrideAttribute(element, annotation, attributes, attributeName, attributeName);
970949
}
971950
}
972951
}
952+
953+
private void overrideAttribute(AnnotatedElement element, Annotation annotation,
954+
AnnotationAttributes attributes, String sourceAttributeName, String targetAttributeName) {
955+
956+
Object value = AnnotationUtils.getValue(annotation, sourceAttributeName);
957+
Object adaptedValue = AnnotationUtils.adaptValue(element, value, this.classValuesAsString,
958+
this.nestedAnnotationsAsMap);
959+
attributes.put(targetAttributeName, adaptedValue);
960+
}
961+
973962
}
974963

975964
}

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

Lines changed: 17 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,7 @@ public abstract class AnnotationUtils {
107107
* An object that can be stored in {@link AnnotationAttributes} as a
108108
* placeholder for an attribute's declared default value.
109109
*/
110-
private static final Object DEFAULT_VALUE_PLACEHOLDER = "<SPRING DEFAULT VALUE PLACEHOLDER>";
110+
private static final Object DEFAULT_VALUE_PLACEHOLDER = new String("<SPRING DEFAULT VALUE PLACEHOLDER>");
111111

112112
private static final Map<AnnotationCacheKey, Annotation> findAnnotationCache =
113113
new ConcurrentReferenceHashMap<AnnotationCacheKey, Annotation>(256);
@@ -803,15 +803,15 @@ public static AnnotationAttributes getAnnotationAttributes(AnnotatedElement anno
803803
* <p>This method provides fully recursive annotation reading capabilities on par with
804804
* the reflection-based {@link org.springframework.core.type.StandardAnnotationMetadata}.
805805
*
806-
* <p><strong>NOTE</strong>: this variant of {@code getAnnotationAttributes()} is
807-
* only intended for use within the framework. Specifically, the
808-
* {@code defaultValuesAsPlaceholder} flag can be set to {@code true} in order to
809-
* support processing of attribute aliases while merging attributes within an annotation
810-
* hierarchy. If this method is invoked with {@code defaultValuesAsPlaceholder} set to
811-
* {@code true}:
806+
* <p><strong>NOTE</strong>: This variant of {@code getAnnotationAttributes()} is
807+
* only intended for use within the framework. Specifically, the {@code mergeMode} flag
808+
* can be set to {@code true} in order to support processing of attribute aliases while
809+
* merging attributes within an annotation hierarchy. When running in <em>merge mode</em>,
810+
* the following special rules apply:
812811
* <ol>
813812
* <li>The supplied annotation will <strong>not</strong> be
814813
* {@linkplain #synthesizeAnnotation synthesized} before retrieving its attributes.</li>
814+
* <li>Default values will be replaced with {@link #DEFAULT_VALUE_PLACEHOLDER}.</li>
815815
* <li>The resulting, merged annotation attributes should eventually be
816816
* {@linkplain #postProcessAnnotationAttributes post-processed} in order to
817817
* ensure that placeholders have been replaced by actual default values and
@@ -828,17 +828,17 @@ public static AnnotationAttributes getAnnotationAttributes(AnnotatedElement anno
828828
* {@link AnnotationAttributes} maps (for compatibility with
829829
* {@link org.springframework.core.type.AnnotationMetadata}) or to preserve them as
830830
* {@code Annotation} instances
831-
* @param defaultValuesAsPlaceholder whether to replace default values with
832-
* {@link #DEFAULT_VALUE_PLACEHOLDER} or leave them as is
831+
* @param mergeMode whether the annotation attributes should be created
832+
* using <em>merge mode</em>
833833
* @return the annotation attributes (a specialized Map) with attribute names as keys
834834
* and corresponding attribute values as values; never {@code null}
835835
* @since 4.2
836836
* @see #postProcessAnnotationAttributes
837837
*/
838838
static AnnotationAttributes getAnnotationAttributes(AnnotatedElement annotatedElement, Annotation annotation,
839-
boolean classValuesAsString, boolean nestedAnnotationsAsMap, boolean defaultValuesAsPlaceholder) {
839+
boolean classValuesAsString, boolean nestedAnnotationsAsMap, boolean mergeMode) {
840840

841-
if (!defaultValuesAsPlaceholder) {
841+
if (!mergeMode) {
842842
annotation = synthesizeAnnotation(annotation, annotatedElement);
843843
}
844844

@@ -848,7 +848,7 @@ static AnnotationAttributes getAnnotationAttributes(AnnotatedElement annotatedEl
848848
try {
849849
Object value = method.invoke(annotation);
850850
Object defaultValue = method.getDefaultValue();
851-
if (defaultValuesAsPlaceholder && (defaultValue != null)) {
851+
if (mergeMode && (defaultValue != null)) {
852852
if (ObjectUtils.nullSafeEquals(value, defaultValue)) {
853853
value = DEFAULT_VALUE_PLACEHOLDER;
854854
}
@@ -1390,8 +1390,8 @@ static void postProcessAnnotationAttributes(AnnotatedElement element, Annotation
13901390
Object value = attributes.get(attributeName);
13911391
Object aliasedValue = attributes.get(aliasedAttributeName);
13921392

1393-
if (!ObjectUtils.nullSafeEquals(value, aliasedValue) && !DEFAULT_VALUE_PLACEHOLDER.equals(value)
1394-
&& !DEFAULT_VALUE_PLACEHOLDER.equals(aliasedValue)) {
1393+
if (!ObjectUtils.nullSafeEquals(value, aliasedValue) && (value != DEFAULT_VALUE_PLACEHOLDER)
1394+
&& (aliasedValue != DEFAULT_VALUE_PLACEHOLDER)) {
13951395
String elementAsString = (element == null ? "unknown element" : element.toString());
13961396
String msg = String.format(
13971397
"In AnnotationAttributes for annotation [%s] declared on [%s], attribute [%s] and its alias [%s] are "
@@ -1402,11 +1402,11 @@ static void postProcessAnnotationAttributes(AnnotatedElement element, Annotation
14021402
}
14031403

14041404
// Replace default values with aliased values...
1405-
if (DEFAULT_VALUE_PLACEHOLDER.equals(value)) {
1405+
if (value == DEFAULT_VALUE_PLACEHOLDER) {
14061406
attributes.put(attributeName,
14071407
adaptValue(element, aliasedValue, classValuesAsString, nestedAnnotationsAsMap));
14081408
}
1409-
if (DEFAULT_VALUE_PLACEHOLDER.equals(aliasedValue)) {
1409+
if (aliasedValue == DEFAULT_VALUE_PLACEHOLDER) {
14101410
attributes.put(aliasedAttributeName,
14111411
adaptValue(element, value, classValuesAsString, nestedAnnotationsAsMap));
14121412
}
@@ -1415,7 +1415,7 @@ static void postProcessAnnotationAttributes(AnnotatedElement element, Annotation
14151415

14161416
for (String attributeName : attributes.keySet()) {
14171417
Object value = attributes.get(attributeName);
1418-
if (DEFAULT_VALUE_PLACEHOLDER.equals(value)) {
1418+
if (value == DEFAULT_VALUE_PLACEHOLDER) {
14191419
attributes.put(attributeName,
14201420
adaptValue(element, getDefaultValue(annotationType, attributeName), classValuesAsString,
14211421
nestedAnnotationsAsMap));

0 commit comments

Comments
 (0)