AnnotationAttributes

作用

按照我的理解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实现的。

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值