作用
按照我的理解AnnotationAttributes是为了存储注解属性或者信息的,可以通过org.springframework.core.annotation.AnnotationUtils.getAnnotationAttributes(annotation);得到
比如:
@ComponentScan
public class Math {
public static void main(String[] args) {
Annotation annotation= Math.class.getAnnotation(ComponentScan.class);
System.out.println("annotationType=>"+annotation.annotationType());
AnnotationAttributes ComponentScanAnnotationAttributes= (AnnotationAttributes) AnnotationUtils.getAnnotationAttributes(annotation);
ComponentScanAnnotationAttributes.forEach((key,value) ->{
System.out.println(key+"=>"+value);
});
//如果不强转,就直接得到了Map
Map<String,Object> map=AnnotationUtils.getAnnotationAttributes(annotation);
Set<String> set=map.keySet();
for(String key:set){
System.out.println(key+"=>"+map.get(key));
}
}
}
输出如下
annotationType=>interface org.springframework.context.annotation.ComponentScan
basePackageClasses=>[Ljava.lang.Class;@1563da5
basePackages=>[Ljava.lang.String;@2bbf4b8b
excludeFilters=>[Lorg.springframework.context.annotation.ComponentScan$Filter;@30a3107a
includeFilters=>[Lorg.springframework.context.annotation.ComponentScan$Filter;@33c7e1bb
lazyInit=>false
nameGenerator=>interface org.springframework.beans.factory.support.BeanNameGenerator
resourcePattern=>**/*.class
scopeResolver=>class org.springframework.context.annotation.AnnotationScopeMetadataResolver
scopedProxy=>DEFAULT
useDefaultFilters=>true
value=>[Ljava.lang.String;@2bbf4b8b
SimpleName=>BeanNameGenerator
当然也可以获取注解的注解
构造函数以及成员
public class AnnotationAttributes extends LinkedHashMap<String, Object> {
private static final String UNKNOWN = "unknown";
//表示注解类型
@Nullable
private final Class<? extends Annotation> annotationType;
//未知
final String displayName;
boolean validated = false;
public AnnotationAttributes() {
this.annotationType = null;
this.displayName = UNKNOWN;
}
/*
AnnotationAttributes 继承了LinkedHashMap,所以这个构造方法通过initialCapacity初始化指定容量的空间
*/
public AnnotationAttributes(int initialCapacity) {
super(initialCapacity);
this.annotationType = null;
this.displayName = UNKNOWN;
}
public AnnotationAttributes(Map<String, Object> map) {
super(map);
this.annotationType = null;
this.displayName = UNKNOWN;
}
public AnnotationAttributes(AnnotationAttributes other) {
super(other);
this.annotationType = other.annotationType;
this.displayName = other.displayName;
this.validated = other.validated;
}
public AnnotationAttributes(Class<? extends Annotation> annotationType) {
Assert.notNull(annotationType, "'annotationType' must not be null");
this.annotationType = annotationType;
this.displayName = annotationType.getName();
}
AnnotationAttributes(Class<? extends Annotation> annotationType, boolean validated) {
Assert.notNull(annotationType, "'annotationType' must not be null");
this.annotationType = annotationType;
this.displayName = annotationType.getName();
this.validated = validated;
}
public AnnotationAttributes(String annotationType, @Nullable ClassLoader classLoader) {
Assert.notNull(annotationType, "'annotationType' must not be null");
this.annotationType = getAnnotationType(annotationType, classLoader);
this.displayName = annotationType;
}
}
可以看到,AnnotationAttributes 继承了LinkedHashMap,我们可以像遍历map那样遍历它,如文章开头代码。
主要方法
/**
得到注解类型
* @since 4.2
*/
@Nullable
public Class<? extends Annotation> annotationType() {
return this.annotationType;
}
/**
得到类型为String的注解内部属性值。
*/
public String getString(String attributeName) {
return getRequiredAttribute(attributeName, String.class);
}
/**
得到类型为String数组的注解内部属性值。
*/
public String[] getStringArray(String attributeName) {
return getRequiredAttribute(attributeName, String[].class);
}
/**
得到类型为Boolean的注解内部属性值。
*/
public boolean getBoolean(String attributeName) {
return getRequiredAttribute(attributeName, Boolean.class);
}
/**
得到类型为Number的注解内部属性值
*/
@SuppressWarnings("unchecked")
public <N extends Number> N getNumber(String attributeName) {
return (N) getRequiredAttribute(attributeName, Number.class);
}
/**
得到类型为Enum的注解内部属性值
*/
@SuppressWarnings("unchecked")
public <E extends Enum<?>> E getEnum(String attributeName) {
return (E) getRequiredAttribute(attributeName, Enum.class);
}
/**
得到类型为Class的注解内部属性值
比如在ComponentScan注解内部有一个属性为:
Class<? extends BeanNameGenerator> nameGenerator() default BeanNameGenerator.class;
*/
@SuppressWarnings("unchecked")
public <T> Class<? extends T> getClass(String attributeName) {
return getRequiredAttribute(attributeName, Class.class);
}
/**
得到类型为Class数组的注解内部属性值
*/
public Class<?>[] getClassArray(String attributeName) {
return getRequiredAttribute(attributeName, Class[].class);
}
/**
得到类型为Annotation的注解内部属性值
* @since 4.2
*/
public AnnotationAttributes getAnnotation(String attributeName) {
return getRequiredAttribute(attributeName, AnnotationAttributes.class);
}
/**
得到类型为Annotation的注解内部属性值,需指定注解的Class
* @since 4.2
*/
public <A extends Annotation> A getAnnotation(String attributeName, Class<A> annotationType) {
return getRequiredAttribute(attributeName, annotationType);
}
/**
得到类型为Annotation数组的注解内部属性值
*/
public AnnotationAttributes[] getAnnotationArray(String attributeName) {
return getRequiredAttribute(attributeName, AnnotationAttributes[].class);
}
/**
* @since 4.2
*/
@SuppressWarnings("unchecked")
public <A extends Annotation> A[] getAnnotationArray(String attributeName, Class<A> annotationType) {
Object array = Array.newInstance(annotationType, 0);
return (A[]) getRequiredAttribute(attributeName, array.getClass());
}
/**
将Map转化为AnnotationAttributes
*/
@Nullable
public static AnnotationAttributes fromMap(@Nullable Map<String, Object> map) {
if (map == null) {
return null;
}
if (map instanceof AnnotationAttributes) {
return (AnnotationAttributes) map;
}
return new AnnotationAttributes(map);
}
核心方法 getRequiredAttribute
private <T> T getRequiredAttribute(String attributeName, Class<T> expectedType) {
Assert.hasText(attributeName, "'attributeName' must not be null or empty");
Object value = get(attributeName);//调用上一层Map的get的方法
assertAttributePresence(attributeName, value);//判断value是否为空
assertNotException(attributeName, value);//判断是否抛出异常
//getComponentType用于返回表示数组的组件类型的Class
//只有数组类型才会有getComponentType,所以这里意思是
//如果是数组类型,并且是数组类型正确,就,,,,这个暂时没有理解,如果有知道的,请在下方评论
if (!expectedType.isInstance(value) && expectedType.isArray() &&
expectedType.getComponentType().isInstance(value)) {
Object array = Array.newInstance(expectedType.getComponentType(), 1);
Array.set(array, 0, value);
value = array;
}
assertAttributeType(attributeName, value, expectedType);//检查类型是否正确
return (T) value;
}
private void assertAttributePresence(String attributeName, Object attributeValue) {
Assert.notNull(attributeValue, () -> String.format(
"Attribute '%s' not found in attributes for annotation [%s]",
attributeName, this.displayName));
}
private void assertNotException(String attributeName, Object attributeValue) {
if (attributeValue instanceof Throwable) {
throw new IllegalArgumentException(String.format(
"Attribute '%s' for annotation [%s] was not resolvable due to exception [%s]",
attributeName, this.displayName, attributeValue), (Throwable) attributeValue);
}
}
private void assertAttributeType(String attributeName, Object attributeValue, Class<?> expectedType) {
if (!expectedType.isInstance(attributeValue)) {
throw new IllegalArgumentException(String.format(
"Attribute '%s' is of type %s, but %s was expected in attributes for annotation [%s]",
attributeName, attributeValue.getClass().getSimpleName(), expectedType.getSimpleName(),
this.displayName));
}
}
以上那些get方法都是基于getRequiredAttribute实现的。