Skip to content

Commit c809324

Browse files
committed
Complete documentation of synthesized annotations
Issue: SPR-11512
1 parent b6f2d95 commit c809324

File tree

2 files changed

+61
-32
lines changed

2 files changed

+61
-32
lines changed

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -927,7 +927,7 @@ private static class MergedAnnotationAttributesProcessor implements Processor<An
927927
public AnnotationAttributes process(AnnotatedElement annotatedElement, Annotation annotation, int metaDepth) {
928928
boolean found = annotation.annotationType().getName().equals(this.annotationTypeName);
929929
return (found ? AnnotationUtils.getAnnotationAttributes(annotatedElement, annotation,
930-
this.classValuesAsString, this.nestedAnnotationsAsMap, true, false) : null);
930+
this.classValuesAsString, this.nestedAnnotationsAsMap, true) : null);
931931
}
932932

933933
@Override

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

Lines changed: 60 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -102,12 +102,12 @@ public abstract class AnnotationUtils {
102102
*/
103103
public static final String VALUE = "value";
104104

105+
105106
/**
106107
* An object that can be stored in {@link AnnotationAttributes} as a
107108
* placeholder for an attribute's declared default value.
108109
*/
109-
public static final Object DEFAULT_VALUE_PLACEHOLDER = "<SPRING DEFAULT VALUE PLACEHOLDER>";
110-
110+
private static final Object DEFAULT_VALUE_PLACEHOLDER = "<SPRING DEFAULT VALUE PLACEHOLDER>";
111111

112112
private static final Map<AnnotationCacheKey, Annotation> findAnnotationCache =
113113
new ConcurrentReferenceHashMap<AnnotationCacheKey, Annotation>(256);
@@ -709,6 +709,7 @@ public static boolean isInJavaLangAnnotationPackage(String annotationType) {
709709
* @param annotation the annotation to retrieve the attributes for
710710
* @return the Map of annotation attributes, with attribute names as keys and
711711
* corresponding attribute values as values; never {@code null}
712+
* @see #getAnnotationAttributes(AnnotatedElement, Annotation)
712713
* @see #getAnnotationAttributes(Annotation, boolean, boolean)
713714
* @see #getAnnotationAttributes(AnnotatedElement, Annotation, boolean, boolean)
714715
*/
@@ -723,7 +724,7 @@ public static Map<String, Object> getAnnotationAttributes(Annotation annotation)
723724
* <p>Note: This method actually returns an {@link AnnotationAttributes} instance.
724725
* However, the {@code Map} signature has been preserved for binary compatibility.
725726
* @param annotation the annotation to retrieve the attributes for
726-
* @param classValuesAsString whether to turn Class references into Strings (for
727+
* @param classValuesAsString whether to convert Class references into Strings (for
727728
* compatibility with {@link org.springframework.core.type.AnnotationMetadata})
728729
* or to preserve them as Class references
729730
* @return the Map of annotation attributes, with attribute names as keys and
@@ -742,10 +743,10 @@ public static Map<String, Object> getAnnotationAttributes(Annotation annotation,
742743
* @param classValuesAsString whether to convert Class references into Strings (for
743744
* compatibility with {@link org.springframework.core.type.AnnotationMetadata})
744745
* or to preserve them as Class references
745-
* @param nestedAnnotationsAsMap whether to turn nested Annotation instances into
746+
* @param nestedAnnotationsAsMap whether to convert nested annotations into
746747
* {@link AnnotationAttributes} maps (for compatibility with
747748
* {@link org.springframework.core.type.AnnotationMetadata}) or to preserve them as
748-
* Annotation instances
749+
* {@code Annotation} instances
749750
* @return the annotation attributes (a specialized Map) with attribute names as keys
750751
* and corresponding attribute values as values; never {@code null}
751752
* @since 3.1.1
@@ -760,9 +761,11 @@ public static AnnotationAttributes getAnnotationAttributes(Annotation annotation
760761
* <p>Equivalent to calling {@link #getAnnotationAttributes(AnnotatedElement, Annotation, boolean, boolean)}
761762
* with the {@code classValuesAsString} and {@code nestedAnnotationsAsMap} parameters
762763
* set to {@code false}.
764+
* @param annotatedElement the element that is annotated with the supplied annotation;
765+
* may be {@code null} if unknown
763766
* @param annotation the annotation to retrieve the attributes for
764-
* @return the Map of annotation attributes, with attribute names as keys and
765-
* corresponding attribute values as values; never {@code null}
767+
* @return the annotation attributes (a specialized Map) with attribute names as keys
768+
* and corresponding attribute values as values; never {@code null}
766769
* @see #getAnnotationAttributes(AnnotatedElement, Annotation, boolean, boolean)
767770
* @since 4.2
768771
*/
@@ -774,27 +777,24 @@ public static AnnotationAttributes getAnnotationAttributes(AnnotatedElement anno
774777
* Retrieve the given annotation's attributes as an {@link AnnotationAttributes} map.
775778
* <p>This method provides fully recursive annotation reading capabilities on par with
776779
* the reflection-based {@link org.springframework.core.type.StandardAnnotationMetadata}.
777-
* @param annotatedElement the element that is annotated with the supplied annotation,
778-
* used for contextual logging; may be {@code null} if unknown
780+
* @param annotatedElement the element that is annotated with the supplied annotation;
781+
* may be {@code null} if unknown
779782
* @param annotation the annotation to retrieve the attributes for
780783
* @param classValuesAsString whether to convert Class references into Strings (for
781784
* compatibility with {@link org.springframework.core.type.AnnotationMetadata})
782785
* or to preserve them as Class references
783-
* @param nestedAnnotationsAsMap whether to convert nested Annotation instances into
786+
* @param nestedAnnotationsAsMap whether to convert nested annotations into
784787
* {@link AnnotationAttributes} maps (for compatibility with
785788
* {@link org.springframework.core.type.AnnotationMetadata}) or to preserve them as
786-
* Annotation instances
787-
* @param defaultValuesAsPlaceholder whether to replace default values with
788-
* {@link #DEFAULT_VALUE_PLACEHOLDER} or leave them as is
789+
* {@code Annotation} instances
789790
* @return the annotation attributes (a specialized Map) with attribute names as keys
790791
* and corresponding attribute values as values; never {@code null}
791792
* @since 4.2
792793
*/
793794
public static AnnotationAttributes getAnnotationAttributes(AnnotatedElement annotatedElement,
794795
Annotation annotation, boolean classValuesAsString, boolean nestedAnnotationsAsMap) {
795796

796-
return getAnnotationAttributes(annotatedElement, annotation, classValuesAsString, nestedAnnotationsAsMap,
797-
false, true);
797+
return getAnnotationAttributes(annotatedElement, annotation, classValuesAsString, nestedAnnotationsAsMap, false);
798798
}
799799

800800
/**
@@ -803,29 +803,42 @@ 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-
* @param annotatedElement the element that is annotated with the supplied annotation,
807-
* used for contextual logging; may be {@code null} if unknown
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}:
812+
* <ol>
813+
* <li>The supplied annotation will <strong>not</strong> be
814+
* {@linkplain #synthesizeAnnotation synthesized} before retrieving its attributes.</li>
815+
* <li>The resulting, merged annotation attributes should eventually be
816+
* {@linkplain #postProcessAnnotationAttributes post-processed} in order to
817+
* ensure that placeholders have been replaced by actual default values and
818+
* in order to enforce {@code @AliasFor} semantics.</li>
819+
* </ol>
820+
*
821+
* @param annotatedElement the element that is annotated with the supplied annotation;
822+
* may be {@code null} if unknown
808823
* @param annotation the annotation to retrieve the attributes for
809824
* @param classValuesAsString whether to convert Class references into Strings (for
810825
* compatibility with {@link org.springframework.core.type.AnnotationMetadata})
811826
* or to preserve them as Class references
812-
* @param nestedAnnotationsAsMap whether to convert nested Annotation instances into
827+
* @param nestedAnnotationsAsMap whether to convert nested annotations into
813828
* {@link AnnotationAttributes} maps (for compatibility with
814829
* {@link org.springframework.core.type.AnnotationMetadata}) or to preserve them as
815-
* Annotation instances
830+
* {@code Annotation} instances
816831
* @param defaultValuesAsPlaceholder whether to replace default values with
817832
* {@link #DEFAULT_VALUE_PLACEHOLDER} or leave them as is
818-
* @param synthesizeAnnotation whether or not the annotation should be
819-
* {@linkplain #synthesizeAnnotation synthesized} before processing
820833
* @return the annotation attributes (a specialized Map) with attribute names as keys
821834
* and corresponding attribute values as values; never {@code null}
822835
* @since 4.2
836+
* @see #postProcessAnnotationAttributes
823837
*/
824-
static AnnotationAttributes getAnnotationAttributes(AnnotatedElement annotatedElement,
825-
Annotation annotation, boolean classValuesAsString, boolean nestedAnnotationsAsMap,
826-
boolean defaultValuesAsPlaceholder, boolean synthesizeAnnotation) {
838+
static AnnotationAttributes getAnnotationAttributes(AnnotatedElement annotatedElement, Annotation annotation,
839+
boolean classValuesAsString, boolean nestedAnnotationsAsMap, boolean defaultValuesAsPlaceholder) {
827840

828-
if (synthesizeAnnotation) {
841+
if (!defaultValuesAsPlaceholder) {
829842
annotation = synthesizeAnnotation(annotation, annotatedElement);
830843
}
831844

@@ -861,13 +874,13 @@ static AnnotationAttributes getAnnotationAttributes(AnnotatedElement annotatedEl
861874
* @param annotatedElement the element that is annotated, used for contextual
862875
* logging; may be {@code null} if unknown
863876
* @param value the annotation attribute value
864-
* @param classValuesAsString whether to turn Class references into Strings (for
877+
* @param classValuesAsString whether to convert Class references into Strings (for
865878
* compatibility with {@link org.springframework.core.type.AnnotationMetadata})
866879
* or to preserve them as Class references
867-
* @param nestedAnnotationsAsMap whether to turn nested Annotation instances into
880+
* @param nestedAnnotationsAsMap whether to convert nested annotations into
868881
* {@link AnnotationAttributes} maps (for compatibility with
869882
* {@link org.springframework.core.type.AnnotationMetadata}) or to preserve them as
870-
* Annotation instances
883+
* {@code Annotation} instances
871884
* @return the adapted value, or the original value if no adaptation is needed
872885
*/
873886
static Object adaptValue(AnnotatedElement annotatedElement, Object value, boolean classValuesAsString,
@@ -1334,12 +1347,28 @@ static List<Method> getAttributeMethods(Class<? extends Annotation> annotationTy
13341347
}
13351348

13361349
/**
1337-
* TODO Document postProcessAnnotationAttributes().
1350+
* Post-process the supplied {@link AnnotationAttributes}.
13381351
*
1339-
* @param element the element that is annotated with the supplied annotation,
1340-
* used for contextual logging; may be {@code null} if unknown
1352+
* <p>Specifically, this method enforces <em>attribute alias</em> semantics
1353+
* for annotation attributes that are annotated with {@link AliasFor @AliasFor}
1354+
* and replaces {@linkplain #DEFAULT_VALUE_PLACEHOLDER placeholders} with their
1355+
* original default values.
1356+
*
1357+
* @param element the element that is annotated with an annotation or
1358+
* annotation hierarchy from which the supplied attributes were created;
1359+
* may be {@code null} if unknown
13411360
* @param attributes the annotation attributes to post-process
1361+
* @param classValuesAsString whether to convert Class references into Strings (for
1362+
* compatibility with {@link org.springframework.core.type.AnnotationMetadata})
1363+
* or to preserve them as Class references
1364+
* @param nestedAnnotationsAsMap whether to convert nested annotations into
1365+
* {@link AnnotationAttributes} maps (for compatibility with
1366+
* {@link org.springframework.core.type.AnnotationMetadata}) or to preserve them as
1367+
* {@code Annotation} instances
13421368
* @since 4.2
1369+
* @see #getAnnotationAttributes(AnnotatedElement, Annotation, boolean, boolean, boolean)
1370+
* @see #DEFAULT_VALUE_PLACEHOLDER
1371+
* @see #getDefaultValue(Class, String)
13431372
*/
13441373
static void postProcessAnnotationAttributes(AnnotatedElement element, AnnotationAttributes attributes,
13451374
boolean classValuesAsString, boolean nestedAnnotationsAsMap) {

0 commit comments

Comments
 (0)