@ -53,7 +53,7 @@ import org.springframework.util.MultiValueMap;
@@ -53,7 +53,7 @@ import org.springframework.util.MultiValueMap;
*
* < h3 > Find vs . Get Semantics < / h3 >
* < p > The search algorithms used by methods in this class follow either
* < em > find < / em > or < em > get < / em > semantics . Consult the Javadoc for each
* < em > find < / em > or < em > get < / em > semantics . Consult the javadocs for each
* individual method for details on which search algorithm is used .
*
* < p > < strong > Get semantics < / strong > are limited to searching for annotations
@ -98,14 +98,13 @@ public class AnnotatedElementUtils {
@@ -98,14 +98,13 @@ public class AnnotatedElementUtils {
/ * *
* Get the fully qualified class names of all meta - annotation
* types < em > present < / em > on the annotation ( of the specified
* { @code annotationType } ) on the supplied { @link AnnotatedElement } .
* Get the fully qualified class names of all meta - annotation types
* < em > present < / em > on the annotation ( of the specified { @code annotationType } )
* on the supplied { @link AnnotatedElement } .
* < p > This method follows < em > get semantics < / em > as described in the
* { @linkplain AnnotatedElementUtils class - level Javadoc } .
* @param element the annotated element ; never { @code null }
* @param annotationType the annotation type on which to find
* meta - annotations ; never { @code null }
* { @linkplain AnnotatedElementUtils class - level javadoc } .
* @param element the annotated element
* @param annotationType the annotation type on which to find meta - annotations
* @return the names of all meta - annotations present on the annotation ,
* or { @code null } if not found
* @since 4 . 2
@ -113,8 +112,28 @@ public class AnnotatedElementUtils {
@@ -113,8 +112,28 @@ public class AnnotatedElementUtils {
* @see # hasMetaAnnotationTypes
* /
public static Set < String > getMetaAnnotationTypes ( AnnotatedElement element , Class < ? extends Annotation > annotationType ) {
Assert . notNull ( element , "AnnotatedElement must not be null" ) ;
Assert . notNull ( annotationType , "annotationType must not be null" ) ;
return getMetaAnnotationTypes ( element , annotationType . getName ( ) ) ;
final Set < String > types = new LinkedHashSet < String > ( ) ;
try {
Annotation annotation = element . getAnnotation ( annotationType ) ;
if ( annotation ! = null ) {
searchWithGetSemantics ( annotation . annotationType ( ) , annotationType , null , new SimpleAnnotationProcessor < Object > ( ) {
@Override
public Object process ( AnnotatedElement annotatedElement , Annotation annotation , int metaDepth ) {
types . add ( annotation . annotationType ( ) . getName ( ) ) ;
return CONTINUE ;
}
} , new HashSet < AnnotatedElement > ( ) , 1 ) ;
}
}
catch ( Throwable ex ) {
AnnotationUtils . rethrowAnnotationConfigurationException ( ex ) ;
throw new IllegalStateException ( "Failed to introspect annotations on " + element , ex ) ;
}
return ( ! types . isEmpty ( ) ? types : null ) ;
}
/ * *
@ -122,10 +141,10 @@ public class AnnotatedElementUtils {
@@ -122,10 +141,10 @@ public class AnnotatedElementUtils {
* types < em > present < / em > on the annotation ( of the specified
* { @code annotationName } ) on the supplied { @link AnnotatedElement } .
* < p > This method follows < em > get semantics < / em > as described in the
* { @linkplain AnnotatedElementUtils class - level J avadoc} .
* @param element the annotated element ; never { @code null }
* { @linkplain AnnotatedElementUtils class - level j avadoc} .
* @param element the annotated element
* @param annotationName the fully qualified class name of the annotation
* type on which to find meta - annotations ; never { @code null } or empty
* type on which to find meta - annotations
* @return the names of all meta - annotations present on the annotation ,
* or { @code null } if not found
* @see # getMetaAnnotationTypes ( AnnotatedElement , Class )
@ -134,14 +153,12 @@ public class AnnotatedElementUtils {
@@ -134,14 +153,12 @@ public class AnnotatedElementUtils {
public static Set < String > getMetaAnnotationTypes ( AnnotatedElement element , String annotationName ) {
Assert . notNull ( element , "AnnotatedElement must not be null" ) ;
Assert . hasLength ( annotationName , "annotationName must not be null or empty" ) ;
final Set < String > types = new LinkedHashSet < String > ( ) ;
try {
Annotation annotation = AnnotationUtils . getAnnotation ( element , annotationName ) ;
if ( annotation ! = null ) {
searchWithGetSemantics ( annotation . annotationType ( ) , annotationName , new SimpleAnnotationProcessor < Object > ( ) {
searchWithGetSemantics ( annotation . annotationType ( ) , null , annotationName , new SimpleAnnotationProcessor < Object > ( ) {
@Override
public Object process ( AnnotatedElement annotatedElement , Annotation annotation , int metaDepth ) {
types . add ( annotation . annotationType ( ) . getName ( ) ) ;
@ -163,10 +180,35 @@ public class AnnotatedElementUtils {
@@ -163,10 +180,35 @@ public class AnnotatedElementUtils {
* a < em > composed annotation < / em > that is meta - annotated with an
* annotation of the specified { @code annotationName } .
* < p > This method follows < em > get semantics < / em > as described in the
* { @linkplain AnnotatedElementUtils class - level Javadoc } .
* @param element the annotated element ; never { @code null }
* @param annotationName the fully qualified class name of the meta - annotation
* type to find ; never { @code null } or empty
* { @linkplain AnnotatedElementUtils class - level javadoc } .
* @param element the annotated element
* @param annotationType the annotation type on which to find meta - annotations
* @return { @code true } if a matching meta - annotation is present
* @since 4 . 2 . 3
* @see # getMetaAnnotationTypes
* /
public static boolean hasMetaAnnotationTypes ( AnnotatedElement element , final Class < ? extends Annotation > annotationType ) {
Assert . notNull ( element , "AnnotatedElement must not be null" ) ;
Assert . notNull ( annotationType , "annotationType must not be null" ) ;
return Boolean . TRUE . equals ( searchWithGetSemantics ( element , annotationType , null , new SimpleAnnotationProcessor < Boolean > ( ) {
@Override
public Boolean process ( AnnotatedElement annotatedElement , Annotation annotation , int metaDepth ) {
boolean found = ( annotation . annotationType ( ) = = annotationType ) ;
return ( found & & metaDepth > 0 ? Boolean . TRUE : CONTINUE ) ;
}
} ) ) ;
}
/ * *
* Determine if the supplied { @link AnnotatedElement } is annotated with a
* < em > composed annotation < / em > that is meta - annotated with an annotation
* of the specified { @code annotationName } .
* < p > This method follows < em > get semantics < / em > as described in the
* { @linkplain AnnotatedElementUtils class - level javadoc } .
* @param element the annotated element
* @param annotationName the fully qualified class name of the
* meta - annotation type to find
* @return { @code true } if a matching meta - annotation is present
* @see # getMetaAnnotationTypes
* /
@ -174,7 +216,7 @@ public class AnnotatedElementUtils {
@@ -174,7 +216,7 @@ public class AnnotatedElementUtils {
Assert . notNull ( element , "AnnotatedElement must not be null" ) ;
Assert . hasLength ( annotationName , "annotationName must not be null or empty" ) ;
return Boolean . TRUE . equals ( searchWithGetSemantics ( element , annotationName , new SimpleAnnotationProcessor < Boolean > ( ) {
return Boolean . TRUE . equals ( searchWithGetSemantics ( element , null , annotationName , new SimpleAnnotationProcessor < Boolean > ( ) {
@Override
public Boolean process ( AnnotatedElement annotatedElement , Annotation annotation , int metaDepth ) {
boolean found = annotation . annotationType ( ) . getName ( ) . equals ( annotationName ) ;
@ -190,21 +232,42 @@ public class AnnotatedElementUtils {
@@ -190,21 +232,42 @@ public class AnnotatedElementUtils {
* < p > If this method returns { @code true } , then { @link # getMergedAnnotationAttributes }
* will return a non - null value .
* < p > This method follows < em > get semantics < / em > as described in the
* { @linkplain AnnotatedElementUtils class - level Javadoc } .
*
* @param element the annotated element ; never { @code null }
* @param annotationName the fully qualified class name of the annotation
* type to find ; never { @code null } or empty
* { @linkplain AnnotatedElementUtils class - level javadoc } .
* @param element the annotated element
* @param annotationType the annotation type on which to find meta - annotations
* @return { @code true } if a matching annotation is present
* @since 4 . 2 . 3
* /
public static boolean isAnnotated ( AnnotatedElement element , final Class < ? extends Annotation > annotationType ) {
Assert . notNull ( element , "AnnotatedElement must not be null" ) ;
Assert . notNull ( annotationType , "annotationType must not be null" ) ;
return Boolean . TRUE . equals ( searchWithGetSemantics ( element , annotationType , null , new SimpleAnnotationProcessor < Boolean > ( ) {
@Override
public Boolean process ( AnnotatedElement annotatedElement , Annotation annotation , int metaDepth ) {
boolean found = annotation . annotationType ( ) = = annotationType ;
return ( found ? Boolean . TRUE : CONTINUE ) ;
}
} ) ) ;
}
/ * *
* Determine if an annotation of the specified { @code annotationName } is
* < em > present < / em > on the supplied { @link AnnotatedElement } or within the
* annotation hierarchy < em > above < / em > the specified element .
* < p > If this method returns { @code true } , then { @link # getMergedAnnotationAttributes }
* will return a non - null value .
* < p > This method follows < em > get semantics < / em > as described in the
* { @linkplain AnnotatedElementUtils class - level javadoc } .
* @param element the annotated element
* @param annotationName the fully qualified class name of the annotation type to find
* @return { @code true } if a matching annotation is present
* /
public static boolean isAnnotated ( AnnotatedElement element , final String annotationName ) {
Assert . notNull ( element , "AnnotatedElement must not be null" ) ;
Assert . hasLength ( annotationName , "annotationName must not be null or empty" ) ;
if ( element . getAnnotations ( ) . length = = 0 ) {
return false ;
}
return Boolean . TRUE . equals ( searchWithGetSemantics ( element , annotationName , new SimpleAnnotationProcessor < Boolean > ( ) {
return Boolean . TRUE . equals ( searchWithGetSemantics ( element , null , annotationName , new SimpleAnnotationProcessor < Boolean > ( ) {
@Override
public Boolean process ( AnnotatedElement annotatedElement , Annotation annotation , int metaDepth ) {
boolean found = annotation . annotationType ( ) . getName ( ) . equals ( annotationName ) ;
@ -223,8 +286,8 @@ public class AnnotatedElementUtils {
@@ -223,8 +286,8 @@ public class AnnotatedElementUtils {
* within a single annotation and within the annotation hierarchy .
* < p > This method delegates to { @link # getMergedAnnotationAttributes ( AnnotatedElement , Class ) }
* and { @link AnnotationUtils # synthesizeAnnotation ( Map , Class , AnnotatedElement ) } .
* @param element the annotated element ; never { @code null }
* @param annotationType the annotation type to find ; never { @code null }
* @param element the annotated element
* @param annotationType the annotation type to find
* @return the merged , synthesized { @code Annotation } , or { @code null } if not found
* @since 4 . 2
* @see # getMergedAnnotationAttributes ( AnnotatedElement , Class )
@ -233,7 +296,7 @@ public class AnnotatedElementUtils {
@@ -233,7 +296,7 @@ public class AnnotatedElementUtils {
* /
public static < A extends Annotation > A getMergedAnnotation ( AnnotatedElement element , Class < A > annotationType ) {
AnnotationAttributes attributes = getMergedAnnotationAttributes ( element , annotationType ) ;
return ( ( attributes ! = null ) ? AnnotationUtils . synthesizeAnnotation ( attributes , annotationType , element ) : null ) ;
return ( attributes ! = null ? AnnotationUtils . synthesizeAnnotation ( attributes , annotationType , element ) : null ) ;
}
/ * *
@ -244,8 +307,8 @@ public class AnnotatedElementUtils {
@@ -244,8 +307,8 @@ public class AnnotatedElementUtils {
* < p > { @link AliasFor @AliasFor } semantics are fully supported , both
* within a single annotation and within the annotation hierarchy .
* < p > This method delegates to { @link # getMergedAnnotationAttributes ( AnnotatedElement , String ) } .
* @param element the annotated element ; never { @code null }
* @param annotationType the annotation type to find ; never { @code null }
* @param element the annotated element
* @param annotationType the annotation type to find
* @return the merged { @code AnnotationAttributes } , or { @code null } if not found
* @since 4 . 2
* @see # getMergedAnnotationAttributes ( AnnotatedElement , String , boolean , boolean )
@ -253,17 +316,14 @@ public class AnnotatedElementUtils {
@@ -253,17 +316,14 @@ public class AnnotatedElementUtils {
* @see # getMergedAnnotation ( AnnotatedElement , Class )
* @see # findMergedAnnotation ( AnnotatedElement , Class )
* /
public static AnnotationAttributes getMergedAnnotationAttributes ( AnnotatedElement element , Class < ? extends Annotation > annotationType ) {
Assert . notNull ( annotationType , "annotationType must not be null" ) ;
return getMergedAnnotationAttributes ( element , annotationType . getName ( ) ) ;
}
public static AnnotationAttributes getMergedAnnotationAttributes (
AnnotatedElement element , Class < ? extends Annotation > annotationType ) {
/ * *
* @deprecated As of Spring Framework 4 . 2 , use { @link # getMergedAnnotationAttributes ( AnnotatedElement , String ) } instead .
* /
@Deprecated
public static AnnotationAttributes getAnnotationAttributes ( AnnotatedElement element , String annotationName ) {
return getMergedAnnotationAttributes ( element , annotationName ) ;
Assert . notNull ( annotationType , "annotationType must not be null" ) ;
AnnotationAttributes attributes = searchWithGetSemantics ( element , annotationType , null ,
new MergedAnnotationAttributesProcessor ( annotationType , null , false , false ) ) ;
AnnotationUtils . postProcessAnnotationAttributes ( element , attributes , false , false ) ;
return attributes ;
}
/ * *
@ -275,11 +335,9 @@ public class AnnotatedElementUtils {
@@ -275,11 +335,9 @@ public class AnnotatedElementUtils {
* within a single annotation and within the annotation hierarchy .
* < p > This method delegates to { @link # getMergedAnnotationAttributes ( AnnotatedElement , String , boolean , boolean ) } ,
* supplying { @code false } for { @code classValuesAsString } and { @code nestedAnnotationsAsMap } .
* @param element the annotated element ; never { @code null }
* @param annotationName the fully qualified class name of the annotation
* type to find ; never { @code null } or empty
* @return the merged { @code AnnotationAttributes } , or { @code null } if
* not found
* @param element the annotated element
* @param annotationName the fully qualified class name of the annotation type to find
* @return the merged { @code AnnotationAttributes } , or { @code null } if not found
* @since 4 . 2
* @see # getMergedAnnotationAttributes ( AnnotatedElement , String , boolean , boolean )
* @see # findMergedAnnotationAttributes ( AnnotatedElement , String , boolean , boolean )
@ -290,55 +348,37 @@ public class AnnotatedElementUtils {
@@ -290,55 +348,37 @@ public class AnnotatedElementUtils {
return getMergedAnnotationAttributes ( element , annotationName , false , false ) ;
}
/ * *
* @deprecated As of Spring Framework 4 . 2 , use { @link # getMergedAnnotationAttributes ( AnnotatedElement , String , boolean , boolean ) } instead .
* /
@Deprecated
public static AnnotationAttributes getAnnotationAttributes ( AnnotatedElement element , String annotationName ,
boolean classValuesAsString , boolean nestedAnnotationsAsMap ) {
return getMergedAnnotationAttributes ( element , annotationName , classValuesAsString , nestedAnnotationsAsMap ) ;
}
/ * *
* Get the first annotation of the specified { @code annotationName } within
* the annotation hierarchy < em > above < / em > the supplied { @code element } and
* merge that annotation ' s attributes with < em > matching < / em > attributes from
* annotations in lower levels of the annotation hierarchy .
* < p > Attributes from lower levels in the annotation hierarchy override
* attributes of the same name from higher levels , and
* { @link AliasFor @AliasFor } semantics are fully supported , both
* within a single annotation and within the annotation hierarchy .
* < p > In contrast to { @link # getAllAnnotationAttributes } , the search
* algorithm used by this method will stop searching the annotation
* hierarchy once the first annotation of the specified
* { @code annotationName } has been found . As a consequence , additional
* annotations of the specified { @code annotationName } will be ignored .
* < p > Attributes from lower levels in the annotation hierarchy override attributes
* of the same name from higher levels , and { @link AliasFor @AliasFor } semantics are
* fully supported , both within a single annotation and within the annotation hierarchy .
* < p > In contrast to { @link # getAllAnnotationAttributes } , the search algorithm used by
* this method will stop searching the annotation hierarchy once the first annotation
* of the specified { @code annotationName } has been found . As a consequence ,
* additional annotations of the specified { @code annotationName } will be ignored .
* < p > This method follows < em > get semantics < / em > as described in the
* { @linkplain AnnotatedElementUtils class - level Javadoc } .
* @param element the annotated element ; never { @code null }
* @param annotationName the fully qualified class name of the annotation
* type to find ; never { @code null } or empty
* @param classValuesAsString whether to convert Class references into
* Strings or to preserve them as Class references
* @param nestedAnnotationsAsMap whether to convert nested Annotation
* instances into { @code AnnotationAttributes } maps or to preserve them
* as Annotation instances
* @return the merged { @code AnnotationAttributes } , or { @code null } if
* not found
* { @linkplain AnnotatedElementUtils class - level javadoc } .
* @param element the annotated element
* @param annotationName the fully qualified class name of the annotation type to find
* @param classValuesAsString whether to convert Class references into Strings or to
* preserve them as Class references
* @param nestedAnnotationsAsMap whether to convert nested Annotation instances
* into { @code AnnotationAttributes } maps or to preserve them as Annotation instances
* @return the merged { @code AnnotationAttributes } , or { @code null } if not found
* @since 4 . 2
* @see # findMergedAnnotation ( AnnotatedElement , Class )
* @see # findMergedAnnotationAttributes ( AnnotatedElement , String , boolean , boolean )
* @see # getAllAnnotationAttributes ( AnnotatedElement , String , boolean , boolean )
* /
public static AnnotationAttributes getMergedAnnotationAttributes ( AnnotatedElement element , String annotationName ,
boolean classValuesAsString , boolean nestedAnnotationsAsMap ) {
public static AnnotationAttributes getMergedAnnotationAttributes ( AnnotatedElement element ,
String annotationName , boolean classValuesAsString , boolean nestedAnnotationsAsMap ) {
if ( element . getAnnotations ( ) . length = = 0 ) {
return null ;
}
AnnotationAttributes attributes = searchWithGetSemantics ( element , annotationName ,
new MergedAnnotationAttributesProcessor ( annotationName , classValuesAsString , nestedAnnotationsAsMap ) ) ;
AnnotationAttributes attributes = searchWithGetSemantics ( element , null , annotationName ,
new MergedAnnotationAttributesProcessor ( null , annotationName , classValuesAsString , nestedAnnotationsAsMap ) ) ;
AnnotationUtils . postProcessAnnotationAttributes ( element , attributes , classValuesAsString , nestedAnnotationsAsMap ) ;
return attributes ;
}
@ -352,8 +392,8 @@ public class AnnotatedElementUtils {
@@ -352,8 +392,8 @@ public class AnnotatedElementUtils {
* < p > { @link AliasFor @AliasFor } semantics are fully supported , both
* within a single annotation and within the annotation hierarchy .
* < p > This method delegates to { @link # findMergedAnnotation ( AnnotatedElement , String ) } .
* @param element the annotated element ; never { @code null }
* @param annotationType the annotation type to find ; never { @code null }
* @param element the annotated element
* @param annotationType the annotation type to find
* @return the merged , synthesized { @code Annotation } , or { @code null } if not found
* @since 4 . 2
* @see # findMergedAnnotation ( AnnotatedElement , String )
@ -376,9 +416,8 @@ public class AnnotatedElementUtils {
@@ -376,9 +416,8 @@ public class AnnotatedElementUtils {
* < p > This method delegates to { @link # findMergedAnnotationAttributes ( AnnotatedElement , String , boolean , boolean ) }
* ( supplying { @code false } for { @code classValuesAsString } and { @code nestedAnnotationsAsMap } )
* and { @link AnnotationUtils # synthesizeAnnotation ( Map , Class , AnnotatedElement ) } .
* @param element the annotated element ; never { @code null }
* @param annotationName the fully qualified class name of the annotation
* type to find ; never { @code null } or empty
* @param element the annotated element
* @param annotationName the fully qualified class name of the annotation type to find
* @return the merged , synthesized { @code Annotation } , or { @code null } if not found
* @since 4 . 2
* @see # findMergedAnnotation ( AnnotatedElement , Class )
@ -407,10 +446,9 @@ public class AnnotatedElementUtils {
@@ -407,10 +446,9 @@ public class AnnotatedElementUtils {
* { @code annotationName } has been found . As a consequence , additional
* annotations of the specified { @code annotationName } will be ignored .
* < p > This method follows < em > find semantics < / em > as described in the
* { @linkplain AnnotatedElementUtils class - level Javadoc } .
* @param element the annotated element ; never { @code null }
* @param annotationName the fully qualified class name of the annotation
* type to find ; never { @code null } or empty
* { @linkplain AnnotatedElementUtils class - level javadoc } .
* @param element the annotated element
* @param annotationType the annotation type to find
* @param classValuesAsString whether to convert Class references into
* Strings or to preserve them as Class references
* @param nestedAnnotationsAsMap whether to convert nested Annotation
@ -421,31 +459,84 @@ public class AnnotatedElementUtils {
@@ -421,31 +459,84 @@ public class AnnotatedElementUtils {
* @since 4 . 2
* @see # findMergedAnnotation ( AnnotatedElement , Class )
* @see # getMergedAnnotationAttributes ( AnnotatedElement , String , boolean , boolean )
* @deprecated as of 4 . 2 . 3 ; use { @link # findMergedAnnotation ( AnnotatedElement , Class ) } instead
* /
public static AnnotationAttributes findMergedAnnotationAttributes ( AnnotatedElement element , String annotationName ,
boolean classValuesAsString , boolean nestedAnnotationsAsMap ) {
@Deprecated
public static AnnotationAttributes findMergedAnnotationAttributes ( AnnotatedElement element ,
Class < ? extends Annotation > annotationType , boolean classValuesAsString , boolean nestedAnnotationsAsMap ) {
AnnotationAttributes attributes = searchWithFindSemantics ( element , annotationName ,
new MergedAnnotationAttributesProcessor ( annotationName , classValuesAsString , nestedAnnotationsAsMap ) ) ;
AnnotationAttributes attributes = searchWithFindSemantics ( element , annotationType , null ,
new MergedAnnotationAttributesProcessor ( annotationType , null , classValuesAsString , nestedAnnotationsAsMap ) ) ;
AnnotationUtils . postProcessAnnotationAttributes ( element , attributes , classValuesAsString , nestedAnnotationsAsMap ) ;
return attributes ;
}
/ * *
* Get the annotation attributes of < strong > all < / strong > annotations of
* the specified { @code annotationName } in the annotation hierarchy above
* the supplied { @link AnnotatedElement } and store the results in a
* { @link MultiValueMap } .
* Find the first annotation of the specified { @code annotationName } within
* the annotation hierarchy < em > above < / em > the supplied { @code element } and
* merge that annotation ' s attributes with < em > matching < / em > attributes from
* annotations in lower levels of the annotation hierarchy .
* < p > Attributes from lower levels in the annotation hierarchy override
* attributes of the same name from higher levels , and
* { @link AliasFor @AliasFor } semantics are fully supported , both
* within a single annotation and within the annotation hierarchy .
* < p > In contrast to { @link # getAllAnnotationAttributes } , the search
* algorithm used by this method will stop searching the annotation
* hierarchy once the first annotation of the specified
* { @code annotationName } has been found . As a consequence , additional
* annotations of the specified { @code annotationName } will be ignored .
* < p > This method follows < em > find semantics < / em > as described in the
* { @linkplain AnnotatedElementUtils class - level javadoc } .
* @param element the annotated element
* @param annotationName the fully qualified class name of the annotation type to find
* @param classValuesAsString whether to convert Class references into Strings or to
* preserve them as Class references
* @param nestedAnnotationsAsMap whether to convert nested Annotation instances into
* { @code AnnotationAttributes } maps or to preserve them as Annotation instances
* @return the merged { @code AnnotationAttributes } , or { @code null } if not found
* @since 4 . 2
* @see # findMergedAnnotation ( AnnotatedElement , Class )
* @see # getMergedAnnotationAttributes ( AnnotatedElement , String , boolean , boolean )
* /
public static AnnotationAttributes findMergedAnnotationAttributes ( AnnotatedElement element ,
String annotationName , boolean classValuesAsString , boolean nestedAnnotationsAsMap ) {
AnnotationAttributes attributes = searchWithFindSemantics ( element , null , annotationName ,
new MergedAnnotationAttributesProcessor ( null , annotationName , classValuesAsString , nestedAnnotationsAsMap ) ) ;
AnnotationUtils . postProcessAnnotationAttributes ( element , attributes , classValuesAsString , nestedAnnotationsAsMap ) ;
return attributes ;
}
/ * *
* @deprecated As of Spring Framework 4 . 2 , use { @link # getMergedAnnotationAttributes ( AnnotatedElement , String ) } instead .
* /
@Deprecated
public static AnnotationAttributes getAnnotationAttributes ( AnnotatedElement element , String annotationName ) {
return getMergedAnnotationAttributes ( element , annotationName ) ;
}
/ * *
* @deprecated As of Spring Framework 4 . 2 , use { @link # getMergedAnnotationAttributes ( AnnotatedElement , String , boolean , boolean ) } instead .
* /
@Deprecated
public static AnnotationAttributes getAnnotationAttributes ( AnnotatedElement element , String annotationName ,
boolean classValuesAsString , boolean nestedAnnotationsAsMap ) {
return getMergedAnnotationAttributes ( element , annotationName , classValuesAsString , nestedAnnotationsAsMap ) ;
}
/ * *
* Get the annotation attributes of < strong > all < / strong > annotations of the specified
* { @code annotationName } in the annotation hierarchy above the supplied
* { @link AnnotatedElement } and store the results in a { @link MultiValueMap } .
* < p > Note : in contrast to { @link # getMergedAnnotationAttributes ( AnnotatedElement , String ) } ,
* this method does < em > not < / em > support attribute overrides .
* < p > This method follows < em > get semantics < / em > as described in the
* { @linkplain AnnotatedElementUtils class - level Javadoc } .
* @param element the annotated element ; never { @code null }
* @param annotationName the fully qualified class name of the annotation
* type to find ; never { @code null } or empty
* @return a { @link MultiValueMap } keyed by attribute name , containing
* the annotation attributes from all annotations found , or { @code null }
* if not found
* { @linkplain AnnotatedElementUtils class - level javadoc } .
* @param element the annotated element
* @param annotationName the fully qualified class name of the annotation type to find
* @return a { @link MultiValueMap } keyed by attribute name , containing the annotation
* attributes from all annotations found , or { @code null } if not found
* @see # getAllAnnotationAttributes ( AnnotatedElement , String , boolean , boolean )
* /
public static MultiValueMap < String , Object > getAllAnnotationAttributes ( AnnotatedElement element , String annotationName ) {
@ -460,31 +551,28 @@ public class AnnotatedElementUtils {
@@ -460,31 +551,28 @@ public class AnnotatedElementUtils {
* < p > Note : in contrast to { @link # getMergedAnnotationAttributes ( AnnotatedElement , String ) } ,
* this method does < em > not < / em > support attribute overrides .
* < p > This method follows < em > get semantics < / em > as described in the
* { @linkplain AnnotatedElementUtils class - level Javadoc } .
* @param element the annotated element ; never { @code null }
* @param annotationName the fully qualified class name of the annotation
* type to find ; never { @code null } or empty
* @param classValuesAsString whether to convert Class references into
* Strings or to preserve them as Class references
* @param nestedAnnotationsAsMap whether to convert nested Annotation
* instances into { @code AnnotationAttributes } maps or to preserve them
* as Annotation instances
* @return a { @link MultiValueMap } keyed by attribute name , containing
* the annotation attributes from all annotations found , or { @code null }
* if not found
* { @linkplain AnnotatedElementUtils class - level javadoc } .
* @param element the annotated element
* @param annotationName the fully qualified class name of the annotation type to find
* @param classValuesAsString whether to convert Class references into Strings or to
* preserve them as Class references
* @param nestedAnnotationsAsMap whether to convert nested Annotation instances into
* { @code AnnotationAttributes } maps or to preserve them as Annotation instances
* @return a { @link MultiValueMap } keyed by attribute name , containing the annotation
* attributes from all annotations found , or { @code null } if not found
* /
public static MultiValueMap < String , Object > getAllAnnotationAttributes ( AnnotatedElement element ,
final String annotationName , final boolean classValuesAsString , final boolean nestedAnnotationsAsMap ) {
final MultiValueMap < String , Object > attributesMap = new LinkedMultiValueMap < String , Object > ( ) ;
searchWithGetSemantics ( element , annotationName , new SimpleAnnotationProcessor < Void > ( ) {
searchWithGetSemantics ( element , null , annotationName , new SimpleAnnotationProcessor < Void > ( ) {
@Override
public Void process ( AnnotatedElement annotatedElement , Annotation annotation , int metaDepth ) {
boolean found = annotation . annotationType ( ) . getName ( ) . equals ( annotationName ) ;
if ( found ) {
AnnotationAttributes annotationAttributes = AnnotationUtils . getAnnotationAttributes ( annotation ,
classValuesAsString , nestedAnnotationsAsMap ) ;
AnnotationAttributes annotationAttributes = AnnotationUtils . getAnnotationAttributes (
annotation , classValuesAsString , nestedAnnotationsAsMap ) ;
for ( Map . Entry < String , Object > entry : annotationAttributes . entrySet ( ) ) {
attributesMap . add ( entry . getKey ( ) , entry . getValue ( ) ) ;
}
@ -500,15 +588,19 @@ public class AnnotatedElementUtils {
@@ -500,15 +588,19 @@ public class AnnotatedElementUtils {
/ * *
* Search for annotations of the specified { @code annotationName } on
* the specified { @code element } , following < em > get semantics < / em > .
* @param element the annotated element ; never { @code null }
* @param element the annotated element
* @param annotationType the annotation type on which to find meta - annotations
* @param annotationName the fully qualified class name of the annotation
* type to find ; never { @code null } or empty
* type to find ( as an alternative to { @code annotationType } )
* @param processor the processor to delegate to
* @return the result of the processor , potentially { @code null }
* /
private static < T > T searchWithGetSemantics ( AnnotatedElement element , String annotationName , Processor < T > processor ) {
private static < T > T searchWithGetSemantics ( AnnotatedElement element ,
Class < ? extends Annotation > annotationType , String annotationName , Processor < T > processor ) {
try {
return searchWithGetSemantics ( element , annotationName , processor , new HashSet < AnnotatedElement > ( ) , 0 ) ;
return searchWithGetSemantics (
element , annotationType , annotationName , processor , new HashSet < AnnotatedElement > ( ) , 0 ) ;
}
catch ( Throwable ex ) {
AnnotationUtils . rethrowAnnotationConfigurationException ( ex ) ;
@ -522,42 +614,45 @@ public class AnnotatedElementUtils {
@@ -522,42 +614,45 @@ public class AnnotatedElementUtils {
* have already been < em > visited < / em > .
* < p > The { @code metaDepth } parameter is explained in the
* { @link Processor # process process ( ) } method of the { @link Processor } API .
* @param element the annotated element ; never { @code null }
* @param element the annotated element
* @param annotationType the annotation type on which to find meta - annotations
* @param annotationName the fully qualified class name of the annotation
* type to find ; never { @code null } or empty
* type to find ( as an alternative to { @code annotationType } )
* @param processor the processor to delegate to
* @param visited the set of annotated elements that have already been visited
* @param metaDepth the meta - depth of the annotation
* @return the result of the processor , potentially { @code null }
* /
private static < T > T searchWithGetSemantics ( AnnotatedElement element , String annotationName ,
private static < T > T searchWithGetSemantics ( AnnotatedElement element ,
Class < ? extends Annotation > annotationType , String annotationName ,
Processor < T > processor , Set < AnnotatedElement > visited , int metaDepth ) {
Assert . notNull ( element , "AnnotatedElement must not be null" ) ;
Assert . hasLength ( annotationName , "annotationName must not be null or empty" ) ;
if ( visited . add ( element ) ) {
try {
// Start searching within locally declared annotations
List < Annotation > declaredAnnotations = Arrays . asList ( element . getDeclaredAnnotations ( ) ) ;
T result = searchWithGetSemanticsInAnnotations ( element , declaredAnnotations , annotationName , processor ,
visited , metaDepth ) ;
T result = searchWithGetSemanticsInAnnotations ( element , declaredAnnotations ,
annotationType , annotationName , processor , visited , metaDepth ) ;
if ( result ! = null ) {
return result ;
}
List < Annotation > inheritedAnnotations = new ArrayList < Annotation > ( ) ;
for ( Annotation annotation : element . getAnnotations ( ) ) {
if ( ! declaredAnnotations . contains ( annotation ) ) {
inheritedAnnotations . add ( annotation ) ;
if ( element instanceof Class ) { // otherwise getAnnotations doesn't return anything new
List < Annotation > inheritedAnnotations = new ArrayList < Annotation > ( ) ;
for ( Annotation annotation : element . getAnnotations ( ) ) {
if ( ! declaredAnnotations . contains ( annotation ) ) {
inheritedAnnotations . add ( annotation ) ;
}
}
}
// Continue searching within inherited annotations
result = searchWithGetSemanticsInAnnotations (
element , inheritedAnnotations , annotationName , processor , visited , metaDepth ) ;
if ( result ! = null ) {
return result ;
// Continue searching within inherited annotations
result = searchWithGetSemanticsInAnnotations ( element , inheritedAnnotations ,
annotationType , annotationName , processor , visited , metaDepth ) ;
if ( result ! = null ) {
return result ;
}
}
}
catch ( Exception ex ) {
@ -570,7 +665,7 @@ public class AnnotatedElementUtils {
@@ -570,7 +665,7 @@ public class AnnotatedElementUtils {
/ * *
* This method is invoked by
* { @link # searchWithGetSemantics ( AnnotatedElement , String , Processor , Set , int ) }
* { @link # searchWithGetSemantics ( AnnotatedElement , Class , String , Processor , Set , int ) }
* to perform the actual search within the supplied list of annotations .
* < p > This method should be invoked first with locally declared annotations
* and then subsequently with inherited annotations , thereby allowing
@ -579,22 +674,26 @@ public class AnnotatedElementUtils {
@@ -579,22 +674,26 @@ public class AnnotatedElementUtils {
* { @link Processor # process process ( ) } method of the { @link Processor } API .
* @param annotatedElement the element that is annotated with the supplied
* annotations , used for contextual logging ; may be { @code null } if unknown
* @param annotations the annotations to search in ; never { @code null }
* @param annotations the annotations to search in
* @param annotationType the annotation type on which to find meta - annotations
* @param annotationName the fully qualified class name of the annotation
* type to find ; never { @code null } or empty
* type to find ( as an alternative to { @code annotationType } )
* @param processor the processor to delegate to
* @param visited the set of annotated elements that have already been visited
* @param metaDepth the meta - depth of the annotation
* @return the result of the processor , potentially { @code null }
* @since 4 . 2
* /
private static < T > T searchWithGetSemanticsInAnnotations ( AnnotatedElement annotatedElement , List < Annotation > annotations ,
String annotationName , Processor < T > processor , Set < AnnotatedElement > visited , int metaDepth ) {
private static < T > T searchWithGetSemanticsInAnnotations ( AnnotatedElement annotatedElement ,
List < Annotation > annotations , Class < ? extends Annotation > annotationType , String annotationName ,
Processor < T > processor , Set < AnnotatedElement > visited , int metaDepth ) {
// Search in annotations
for ( Annotation annotation : annotations ) {
if ( ! AnnotationUtils . isInJavaLangAnnotationPackage ( annotation ) & &
( annotation . annotationType ( ) . getName ( ) . equals ( annotationName ) | | metaDepth > 0 ) ) {
( ( annotationType ! = null ? annotation . annotationType ( ) = = annotationType :
annotation . annotationType ( ) . getName ( ) . equals ( annotationName ) ) | |
metaDepth > 0 ) ) {
T result = processor . process ( annotatedElement , annotation , metaDepth ) ;
if ( result ! = null ) {
return result ;
@ -605,8 +704,8 @@ public class AnnotatedElementUtils {
@@ -605,8 +704,8 @@ public class AnnotatedElementUtils {
// Recursively search in meta-annotations
for ( Annotation annotation : annotations ) {
if ( ! AnnotationUtils . isInJavaLangAnnotationPackage ( annotation ) ) {
T result = searchWithGetSemantics (
annotation . annotationType ( ) , annotation Name, processor , visited , metaDepth + 1 ) ;
T result = searchWithGetSemantics ( annotation . annotationType ( ) , annotationType ,
annotationName , processor , visited , metaDepth + 1 ) ;
if ( result ! = null ) {
processor . postProcess ( annotatedElement , annotation , result ) ;
return result ;
@ -620,16 +719,20 @@ public class AnnotatedElementUtils {
@@ -620,16 +719,20 @@ public class AnnotatedElementUtils {
/ * *
* Search for annotations of the specified { @code annotationName } on
* the specified { @code element } , following < em > find semantics < / em > .
* @param element the annotated element ; never { @code null }
* @param element the annotated element
* @param annotationType the annotation type on which to find meta - annotations
* @param annotationName the fully qualified class name of the annotation
* type to find ; never { @code null } or empty
* type to find ( as an alternative to { @code annotationType } )
* @param processor the processor to delegate to
* @return the result of the processor , potentially { @code null }
* @since 4 . 2
* /
private static < T > T searchWithFindSemantics ( AnnotatedElement element , String annotationName , Processor < T > processor ) {
private static < T > T searchWithFindSemantics (
AnnotatedElement element , Class < ? extends Annotation > annotationType , String annotationName , Processor < T > processor ) {
try {
return searchWithFindSemantics ( element , annotationName , processor , new HashSet < AnnotatedElement > ( ) , 0 ) ;
return searchWithFindSemantics (
element , annotationType , annotationName , processor , new HashSet < AnnotatedElement > ( ) , 0 ) ;
}
catch ( Throwable ex ) {
AnnotationUtils . rethrowAnnotationConfigurationException ( ex ) ;
@ -643,17 +746,18 @@ public class AnnotatedElementUtils {
@@ -643,17 +746,18 @@ public class AnnotatedElementUtils {
* have already been < em > visited < / em > .
* < p > The { @code metaDepth } parameter is explained in the
* { @link Processor # process process ( ) } method of the { @link Processor } API .
* @param element the annotated element ; never { @code null }
* @param element the annotated element
* @param annotationType the annotation type on which to find meta - annotations
* @param annotationName the fully qualified class name of the annotation
* type to find ; never { @code null } or empty
* type to find ( as an alternative to { @code annotationType } )
* @param processor the processor to delegate to
* @param visited the set of annotated elements that have already been visited
* @param metaDepth the meta - depth of the annotation
* @return the result of the processor , potentially { @code null }
* @since 4 . 2
* /
private static < T > T searchWithFindSemantics ( AnnotatedElement element , String annotationNam e,
Processor < T > processor , Set < AnnotatedElement > visited , int metaDepth ) {
private static < T > T searchWithFindSemantics ( AnnotatedElement element , Class < ? extends Annotation > annotationTyp e,
String annotationName , Processor < T > processor , Set < AnnotatedElement > visited , int metaDepth ) {
Assert . notNull ( element , "AnnotatedElement must not be null" ) ;
Assert . hasLength ( annotationName , "annotationName must not be null or empty" ) ;
@ -665,8 +769,10 @@ public class AnnotatedElementUtils {
@@ -665,8 +769,10 @@ public class AnnotatedElementUtils {
// Search in local annotations
for ( Annotation annotation : annotations ) {
if ( ! AnnotationUtils . isInJavaLangAnnotationPackage ( annotation )
& & ( annotation . annotationType ( ) . getName ( ) . equals ( annotationName ) | | metaDepth > 0 ) ) {
if ( ! AnnotationUtils . isInJavaLangAnnotationPackage ( annotation ) & &
( ( annotationType ! = null ? annotation . annotationType ( ) = = annotationType :
annotation . annotationType ( ) . getName ( ) . equals ( annotationName ) ) | |
metaDepth > 0 ) ) {
T result = processor . process ( element , annotation , metaDepth ) ;
if ( result ! = null ) {
return result ;
@ -677,8 +783,8 @@ public class AnnotatedElementUtils {
@@ -677,8 +783,8 @@ public class AnnotatedElementUtils {
// Search in meta annotations on local annotations
for ( Annotation annotation : annotations ) {
if ( ! AnnotationUtils . isInJavaLangAnnotationPackage ( annotation ) ) {
T result = searchWithFindSemantics ( annotation . annotationType ( ) , annotationName , processor ,
visited , metaDepth + 1 ) ;
T result = searchWithFindSemantics (
annotation . annotationType ( ) , annotationType , annotationName , processor , visited , metaDepth + 1 ) ;
if ( result ! = null ) {
processor . postProcess ( annotation . annotationType ( ) , annotation , result ) ;
return result ;
@ -691,14 +797,16 @@ public class AnnotatedElementUtils {
@@ -691,14 +797,16 @@ public class AnnotatedElementUtils {
// Search on possibly bridged method
Method resolvedMethod = BridgeMethodResolver . findBridgedMethod ( method ) ;
T result = searchWithFindSemantics ( resolvedMethod , annotationName , processor , visited , metaDepth ) ;
T result = searchWithFindSemantics ( resolvedMethod , annotationType , annotationName ,
processor , visited , metaDepth ) ;
if ( result ! = null ) {
return result ;
}
// Search on methods in interfaces declared locally
Class < ? > [ ] ifcs = method . getDeclaringClass ( ) . getInterfaces ( ) ;
result = searchOnInterfaces ( method , annotationName , processor , visited , metaDepth , ifcs ) ;
result = searchOnInterfaces (
method , annotationType , annotationName , processor , visited , metaDepth , ifcs ) ;
if ( result ! = null ) {
return result ;
}
@ -714,8 +822,8 @@ public class AnnotatedElementUtils {
@@ -714,8 +822,8 @@ public class AnnotatedElementUtils {
try {
Method equivalentMethod = clazz . getDeclaredMethod ( method . getName ( ) , method . getParameterTypes ( ) ) ;
Method resolvedEquivalentMethod = BridgeMethodResolver . findBridgedMethod ( equivalentMethod ) ;
result = searchWithFindSemantics (
resolvedEquivalentMethod , annotationName , processor , visited , metaDepth ) ;
result = searchWithFindSemantics ( resolvedEquivalentMethod , annotationType , annotationName ,
processor , visited , metaDepth ) ;
if ( result ! = null ) {
return result ;
}
@ -725,8 +833,8 @@ public class AnnotatedElementUtils {
@@ -725,8 +833,8 @@ public class AnnotatedElementUtils {
}
// Search on interfaces declared on superclass
result = searchOnInterfaces ( method , annotationName , processor , visited , metaDepth ,
clazz . getInterfaces ( ) ) ;
result = searchOnInterfaces ( method , annotationType , annotation Name , processor , visited ,
metaDepth , clazz . getInterfaces ( ) ) ;
if ( result ! = null ) {
return result ;
}
@ -738,7 +846,8 @@ public class AnnotatedElementUtils {
@@ -738,7 +846,8 @@ public class AnnotatedElementUtils {
// Search on interfaces
for ( Class < ? > ifc : clazz . getInterfaces ( ) ) {
T result = searchWithFindSemantics ( ifc , annotationName , processor , visited , metaDepth ) ;
T result = searchWithFindSemantics (
ifc , annotationType , annotationName , processor , visited , metaDepth ) ;
if ( result ! = null ) {
return result ;
}
@ -747,7 +856,8 @@ public class AnnotatedElementUtils {
@@ -747,7 +856,8 @@ public class AnnotatedElementUtils {
// Search on superclass
Class < ? > superclass = clazz . getSuperclass ( ) ;
if ( superclass ! = null & & Object . class ! = superclass ) {
T result = searchWithFindSemantics ( superclass , annotationName , processor , visited , metaDepth ) ;
T result = searchWithFindSemantics (
superclass , annotationType , annotationName , processor , visited , metaDepth ) ;
if ( result ! = null ) {
return result ;
}
@ -761,14 +871,15 @@ public class AnnotatedElementUtils {
@@ -761,14 +871,15 @@ public class AnnotatedElementUtils {
return null ;
}
private static < T > T searchOnInterfaces ( Method method , String annotationName , Processor < T > processor ,
Set < AnnotatedElement > visited , int metaDepth , Class < ? > [ ] ifcs ) {
private static < T > T searchOnInterfaces ( Method method , Class < ? extends Annotation > annotationType , String annotationName ,
Processor < T > processor , Set < AnnotatedElement > visited , int metaDepth , Class < ? > [ ] ifcs ) {
for ( Class < ? > iface : ifcs ) {
if ( AnnotationUtils . isInterfaceWithAnnotatedMethods ( iface ) ) {
try {
Method equivalentMethod = iface . getMethod ( method . getName ( ) , method . getParameterTypes ( ) ) ;
T result = searchWithFindSemantics ( equivalentMethod , annotationName , processor , visited , metaDepth ) ;
T result = searchWithFindSemantics ( equivalentMethod , annotationType , annotationName ,
processor , visited , metaDepth ) ;
if ( result ! = null ) {
return result ;
}
@ -871,15 +982,18 @@ public class AnnotatedElementUtils {
@@ -871,15 +982,18 @@ public class AnnotatedElementUtils {
* /
private static class MergedAnnotationAttributesProcessor implements Processor < AnnotationAttributes > {
private final Class < ? extends Annotation > annotationType ;
private final String annotationName ;
private final boolean classValuesAsString ;
private final boolean nestedAnnotationsAsMap ;
MergedAnnotationAttributesProcessor ( String annotationName , boolean classValuesAsString ,
boolean nestedAnnotationsAsMap ) {
MergedAnnotationAttributesProcessor ( Class < ? extends Annotation > annotationType , String annotationName ,
boolean classValuesAsString , boolean nestedAnnotationsAsMap ) {
this . annotationType = annotationType ;
this . annotationName = annotationName ;
this . classValuesAsString = classValuesAsString ;
this . nestedAnnotationsAsMap = nestedAnnotationsAsMap ;
@ -887,7 +1001,8 @@ public class AnnotatedElementUtils {
@@ -887,7 +1001,8 @@ public class AnnotatedElementUtils {
@Override
public AnnotationAttributes process ( AnnotatedElement annotatedElement , Annotation annotation , int metaDepth ) {
boolean found = annotation . annotationType ( ) . getName ( ) . equals ( this . annotationName ) ;
boolean found = ( this . annotationType ! = null ? annotation . annotationType ( ) = = this . annotationType :
annotation . annotationType ( ) . getName ( ) . equals ( this . annotationName ) ) ;
return ( found ? AnnotationUtils . getAnnotationAttributes ( annotatedElement , annotation ,
this . classValuesAsString , this . nestedAnnotationsAsMap , true ) : null ) ;
}