@@ -118,6 +118,9 @@ public abstract class AnnotationUtils {
118
118
private static final Map <Class <? extends Annotation >, Boolean > synthesizableCache =
119
119
new ConcurrentReferenceHashMap <Class <? extends Annotation >, Boolean >(256 );
120
120
121
+ private static final Map <Class <? extends Annotation >, Map <String , String >> attributeAliasCache =
122
+ new ConcurrentReferenceHashMap <Class <? extends Annotation >, Map <String , String >>(256 );
123
+
121
124
private static transient Log logger ;
122
125
123
126
@@ -1058,20 +1061,38 @@ public static <A extends Annotation> A synthesizeAnnotation(A annotation, Annota
1058
1061
return annotation ;
1059
1062
}
1060
1063
1061
- InvocationHandler handler = new SynthesizedAnnotationInvocationHandler (annotatedElement , annotation , getAliasMap (annotationType ));
1064
+ InvocationHandler handler = new SynthesizedAnnotationInvocationHandler (annotatedElement , annotation ,
1065
+ getAttributeAliasMap (annotationType ));
1062
1066
A synthesizedAnnotation = (A ) Proxy .newProxyInstance (ClassUtils .getDefaultClassLoader (), new Class <?>[] {
1063
1067
(Class <A >) annotationType , SynthesizedAnnotation .class }, handler );
1064
1068
1065
1069
return synthesizedAnnotation ;
1066
1070
}
1067
1071
1072
+
1068
1073
/**
1069
- * TODO Document getAliasMap().
1074
+ * Get a map of all attribute alias pairs, declared via {@code @AliasFor}
1075
+ * in the supplied annotation type.
1076
+ *
1077
+ * <p>The map is keyed by attribute name with each value representing
1078
+ * the name of the aliased attribute. For each entry {@code [x, y]} in
1079
+ * the map there will be a corresponding {@code [y, x]} entry in the map.
1080
+ *
1081
+ * <p>An empty return value implies that the annotation does not declare
1082
+ * any attribute aliases.
1083
+ *
1084
+ * @param annotationType the annotation type to find attribute aliases in
1085
+ * @return a map containing attribute alias pairs; never {@code null}
1070
1086
* @since 4.2
1071
1087
*/
1072
- private static Map <String , String > getAliasMap (Class <? extends Annotation > annotationType ) {
1088
+ private static Map <String , String > getAttributeAliasMap (Class <? extends Annotation > annotationType ) {
1073
1089
if (annotationType == null ) {
1074
- return null ;
1090
+ return Collections .emptyMap ();
1091
+ }
1092
+
1093
+ Map <String , String > cachedMap = attributeAliasCache .get (annotationType );
1094
+ if (cachedMap != null ) {
1095
+ return cachedMap ;
1075
1096
}
1076
1097
1077
1098
Map <String , String > map = new HashMap <String , String >();
@@ -1082,6 +1103,9 @@ private static Map<String, String> getAliasMap(Class<? extends Annotation> annot
1082
1103
map .put (attributeName , aliasedAttributeName );
1083
1104
}
1084
1105
}
1106
+
1107
+ attributeAliasCache .put (annotationType , map );
1108
+
1085
1109
return map ;
1086
1110
}
1087
1111
@@ -1283,9 +1307,9 @@ static List<Method> getAttributeMethods(Class<? extends Annotation> annotationTy
1283
1307
/**
1284
1308
* TODO Document postProcessAnnotationAttributes().
1285
1309
*
1286
- * @param annotatedElement the element that is annotated with the supplied
1287
- * annotation, used for contextual logging; may be {@code null} if unknown
1288
- * @param attributes the annotation attributes to validate
1310
+ * @param element the element that is annotated with the supplied annotation,
1311
+ * used for contextual logging; may be {@code null} if unknown
1312
+ * @param attributes the annotation attributes to post-process
1289
1313
* @since 4.2
1290
1314
*/
1291
1315
static void postProcessAnnotationAttributes (AnnotatedElement element , AnnotationAttributes attributes ,
@@ -1297,39 +1321,36 @@ static void postProcessAnnotationAttributes(AnnotatedElement element, Annotation
1297
1321
}
1298
1322
1299
1323
Class <? extends Annotation > annotationType = attributes .annotationType ();
1300
- Map <String , String > aliasMap = getAliasMap (annotationType );
1301
1324
1302
1325
// Validate @AliasFor configuration
1303
- if (aliasMap != null ) {
1304
- Set <String > validated = new HashSet <String >();
1305
-
1306
- for (String attributeName : aliasMap .keySet ()) {
1307
- String aliasedAttributeName = aliasMap .get (attributeName );
1308
-
1309
- if (validated .add (attributeName ) && validated .add (aliasedAttributeName )) {
1310
- Object value = attributes .get (attributeName );
1311
- Object aliasedValue = attributes .get (aliasedAttributeName );
1312
-
1313
- if (!ObjectUtils .nullSafeEquals (value , aliasedValue ) && !DEFAULT_VALUE_PLACEHOLDER .equals (value )
1314
- && !DEFAULT_VALUE_PLACEHOLDER .equals (aliasedValue )) {
1315
- String elementAsString = (element == null ? "unknown element" : element .toString ());
1316
- String msg = String .format (
1317
- "In AnnotationAttributes for annotation [%s] declared on [%s], attribute [%s] and its alias [%s] are "
1318
- + "declared with values of [%s] and [%s], but only one declaration is permitted." ,
1319
- annotationType .getName (), elementAsString , attributeName , aliasedAttributeName ,
1320
- ObjectUtils .nullSafeToString (value ), ObjectUtils .nullSafeToString (aliasedValue ));
1321
- throw new AnnotationConfigurationException (msg );
1322
- }
1326
+ Map <String , String > aliasMap = getAttributeAliasMap (annotationType );
1327
+ Set <String > validated = new HashSet <String >();
1328
+ for (String attributeName : aliasMap .keySet ()) {
1329
+ String aliasedAttributeName = aliasMap .get (attributeName );
1330
+
1331
+ if (validated .add (attributeName ) && validated .add (aliasedAttributeName )) {
1332
+ Object value = attributes .get (attributeName );
1333
+ Object aliasedValue = attributes .get (aliasedAttributeName );
1334
+
1335
+ if (!ObjectUtils .nullSafeEquals (value , aliasedValue ) && !DEFAULT_VALUE_PLACEHOLDER .equals (value )
1336
+ && !DEFAULT_VALUE_PLACEHOLDER .equals (aliasedValue )) {
1337
+ String elementAsString = (element == null ? "unknown element" : element .toString ());
1338
+ String msg = String .format (
1339
+ "In AnnotationAttributes for annotation [%s] declared on [%s], attribute [%s] and its alias [%s] are "
1340
+ + "declared with values of [%s] and [%s], but only one declaration is permitted." ,
1341
+ annotationType .getName (), elementAsString , attributeName , aliasedAttributeName ,
1342
+ ObjectUtils .nullSafeToString (value ), ObjectUtils .nullSafeToString (aliasedValue ));
1343
+ throw new AnnotationConfigurationException (msg );
1344
+ }
1323
1345
1324
- // Replace default values with aliased values...
1325
- if (DEFAULT_VALUE_PLACEHOLDER .equals (value )) {
1326
- attributes .put (attributeName ,
1327
- adaptValue (element , aliasedValue , classValuesAsString , nestedAnnotationsAsMap ));
1328
- }
1329
- if (DEFAULT_VALUE_PLACEHOLDER .equals (aliasedValue )) {
1330
- attributes .put (aliasedAttributeName ,
1331
- adaptValue (element , value , classValuesAsString , nestedAnnotationsAsMap ));
1332
- }
1346
+ // Replace default values with aliased values...
1347
+ if (DEFAULT_VALUE_PLACEHOLDER .equals (value )) {
1348
+ attributes .put (attributeName ,
1349
+ adaptValue (element , aliasedValue , classValuesAsString , nestedAnnotationsAsMap ));
1350
+ }
1351
+ if (DEFAULT_VALUE_PLACEHOLDER .equals (aliasedValue )) {
1352
+ attributes .put (aliasedAttributeName ,
1353
+ adaptValue (element , value , classValuesAsString , nestedAnnotationsAsMap ));
1333
1354
}
1334
1355
}
1335
1356
}
0 commit comments