@@ -102,12 +102,12 @@ public abstract class AnnotationUtils {
102
102
*/
103
103
public static final String VALUE = "value" ;
104
104
105
+
105
106
/**
106
107
* An object that can be stored in {@link AnnotationAttributes} as a
107
108
* placeholder for an attribute's declared default value.
108
109
*/
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>" ;
111
111
112
112
private static final Map <AnnotationCacheKey , Annotation > findAnnotationCache =
113
113
new ConcurrentReferenceHashMap <AnnotationCacheKey , Annotation >(256 );
@@ -709,6 +709,7 @@ public static boolean isInJavaLangAnnotationPackage(String annotationType) {
709
709
* @param annotation the annotation to retrieve the attributes for
710
710
* @return the Map of annotation attributes, with attribute names as keys and
711
711
* corresponding attribute values as values; never {@code null}
712
+ * @see #getAnnotationAttributes(AnnotatedElement, Annotation)
712
713
* @see #getAnnotationAttributes(Annotation, boolean, boolean)
713
714
* @see #getAnnotationAttributes(AnnotatedElement, Annotation, boolean, boolean)
714
715
*/
@@ -723,7 +724,7 @@ public static Map<String, Object> getAnnotationAttributes(Annotation annotation)
723
724
* <p>Note: This method actually returns an {@link AnnotationAttributes} instance.
724
725
* However, the {@code Map} signature has been preserved for binary compatibility.
725
726
* @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
727
728
* compatibility with {@link org.springframework.core.type.AnnotationMetadata})
728
729
* or to preserve them as Class references
729
730
* @return the Map of annotation attributes, with attribute names as keys and
@@ -742,10 +743,10 @@ public static Map<String, Object> getAnnotationAttributes(Annotation annotation,
742
743
* @param classValuesAsString whether to convert Class references into Strings (for
743
744
* compatibility with {@link org.springframework.core.type.AnnotationMetadata})
744
745
* 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
746
747
* {@link AnnotationAttributes} maps (for compatibility with
747
748
* {@link org.springframework.core.type.AnnotationMetadata}) or to preserve them as
748
- * Annotation instances
749
+ * {@code Annotation} instances
749
750
* @return the annotation attributes (a specialized Map) with attribute names as keys
750
751
* and corresponding attribute values as values; never {@code null}
751
752
* @since 3.1.1
@@ -760,9 +761,11 @@ public static AnnotationAttributes getAnnotationAttributes(Annotation annotation
760
761
* <p>Equivalent to calling {@link #getAnnotationAttributes(AnnotatedElement, Annotation, boolean, boolean)}
761
762
* with the {@code classValuesAsString} and {@code nestedAnnotationsAsMap} parameters
762
763
* set to {@code false}.
764
+ * @param annotatedElement the element that is annotated with the supplied annotation;
765
+ * may be {@code null} if unknown
763
766
* @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}
766
769
* @see #getAnnotationAttributes(AnnotatedElement, Annotation, boolean, boolean)
767
770
* @since 4.2
768
771
*/
@@ -774,27 +777,24 @@ public static AnnotationAttributes getAnnotationAttributes(AnnotatedElement anno
774
777
* Retrieve the given annotation's attributes as an {@link AnnotationAttributes} map.
775
778
* <p>This method provides fully recursive annotation reading capabilities on par with
776
779
* 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
779
782
* @param annotation the annotation to retrieve the attributes for
780
783
* @param classValuesAsString whether to convert Class references into Strings (for
781
784
* compatibility with {@link org.springframework.core.type.AnnotationMetadata})
782
785
* 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
784
787
* {@link AnnotationAttributes} maps (for compatibility with
785
788
* {@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
789
790
* @return the annotation attributes (a specialized Map) with attribute names as keys
790
791
* and corresponding attribute values as values; never {@code null}
791
792
* @since 4.2
792
793
*/
793
794
public static AnnotationAttributes getAnnotationAttributes (AnnotatedElement annotatedElement ,
794
795
Annotation annotation , boolean classValuesAsString , boolean nestedAnnotationsAsMap ) {
795
796
796
- return getAnnotationAttributes (annotatedElement , annotation , classValuesAsString , nestedAnnotationsAsMap ,
797
- false , true );
797
+ return getAnnotationAttributes (annotatedElement , annotation , classValuesAsString , nestedAnnotationsAsMap , false );
798
798
}
799
799
800
800
/**
@@ -803,29 +803,42 @@ public static AnnotationAttributes getAnnotationAttributes(AnnotatedElement anno
803
803
* <p>This method provides fully recursive annotation reading capabilities on par with
804
804
* the reflection-based {@link org.springframework.core.type.StandardAnnotationMetadata}.
805
805
*
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
808
823
* @param annotation the annotation to retrieve the attributes for
809
824
* @param classValuesAsString whether to convert Class references into Strings (for
810
825
* compatibility with {@link org.springframework.core.type.AnnotationMetadata})
811
826
* 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
813
828
* {@link AnnotationAttributes} maps (for compatibility with
814
829
* {@link org.springframework.core.type.AnnotationMetadata}) or to preserve them as
815
- * Annotation instances
830
+ * {@code Annotation} instances
816
831
* @param defaultValuesAsPlaceholder whether to replace default values with
817
832
* {@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
820
833
* @return the annotation attributes (a specialized Map) with attribute names as keys
821
834
* and corresponding attribute values as values; never {@code null}
822
835
* @since 4.2
836
+ * @see #postProcessAnnotationAttributes
823
837
*/
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 ) {
827
840
828
- if (synthesizeAnnotation ) {
841
+ if (! defaultValuesAsPlaceholder ) {
829
842
annotation = synthesizeAnnotation (annotation , annotatedElement );
830
843
}
831
844
@@ -861,13 +874,13 @@ static AnnotationAttributes getAnnotationAttributes(AnnotatedElement annotatedEl
861
874
* @param annotatedElement the element that is annotated, used for contextual
862
875
* logging; may be {@code null} if unknown
863
876
* @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
865
878
* compatibility with {@link org.springframework.core.type.AnnotationMetadata})
866
879
* 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
868
881
* {@link AnnotationAttributes} maps (for compatibility with
869
882
* {@link org.springframework.core.type.AnnotationMetadata}) or to preserve them as
870
- * Annotation instances
883
+ * {@code Annotation} instances
871
884
* @return the adapted value, or the original value if no adaptation is needed
872
885
*/
873
886
static Object adaptValue (AnnotatedElement annotatedElement , Object value , boolean classValuesAsString ,
@@ -1334,12 +1347,28 @@ static List<Method> getAttributeMethods(Class<? extends Annotation> annotationTy
1334
1347
}
1335
1348
1336
1349
/**
1337
- * TODO Document postProcessAnnotationAttributes() .
1350
+ * Post-process the supplied {@link AnnotationAttributes} .
1338
1351
*
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
1341
1360
* @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
1342
1368
* @since 4.2
1369
+ * @see #getAnnotationAttributes(AnnotatedElement, Annotation, boolean, boolean, boolean)
1370
+ * @see #DEFAULT_VALUE_PLACEHOLDER
1371
+ * @see #getDefaultValue(Class, String)
1343
1372
*/
1344
1373
static void postProcessAnnotationAttributes (AnnotatedElement element , AnnotationAttributes attributes ,
1345
1374
boolean classValuesAsString , boolean nestedAnnotationsAsMap ) {
0 commit comments