org.springframework.core.annotation.AnnotationUtils源码解析与@AliasFor

最近在研究@AliasFor的使用,所以把对应的工具类使用的三个方法源码注释了一下
用法 1: A注解有属性a,b ,用上@AliasFor 这个注解,设置a或者b的其中一个值的时候,另一个属性值也会相等

//========testAliasFor1=====
//@ContextConfiguration(value = "aa.xml", locations = "aa.xml") // 会报错
@ContextConfiguration(value = "aa.xml") // 不会报错
public class AnnotationUtilsTest {


    /**
     * 用法 1 A注解有属性a,b ,用上@AliasFor 这个注解,设置a或者b的其中一个值的时候,另一个属性值也会相等
     * 
     * @spring典型 注解 例子 @RequestMapping
     * @Title testAliasFor1
     * @author 于国帅
     * @date 2019年3月5日 下午2:22:12 void
     */
    @Test
    public void testAliasFor1() {
        ContextConfiguration contextConfiguration = AnnotationUtils.findAnnotation(getClass(), ContextConfiguration.class);
        System.err.println(StringUtils.join(contextConfiguration.value())); //aa.xml
        System.err.println(StringUtils.join(contextConfiguration.locations())); //aa.xml

    }
    }
spring什么时候将使用@AliasFor的注解的属性方法进行注入的呢?

spring在启动时,先利用AnnotationUtils.synthesizeAnnotation方法生成一个代理对象,然后调用代理对象的getAttributeValue方法返回被@AliasFor注释的属性的值

	@SuppressWarnings("unchecked")
	static <A extends Annotation> A synthesizeAnnotation(A annotation, @Nullable Object annotatedElement) {
	    //判断是否是 SynthesizedAnnotation的实例 或者是java和spring工具类自定义的注解
		if (annotation instanceof SynthesizedAnnotation || hasPlainJavaAnnotationsOnly(annotatedElement)) {
			return annotation;
		}
		//返回此注释的注释类型。 即注解.class
		Class<? extends Annotation> annotationType = annotation.annotationType();
		//不是通过@AliasFor 注释修饰的 
		if (!isSynthesizable(annotationType)) {
			return annotation;
		}
		//通过@AliasFor 修饰的  返回一个 动态代理的对象
		DefaultAnnotationAttributeExtractor attributeExtractor =
				new DefaultAnnotationAttributeExtractor(annotation, annotatedElement);
		InvocationHandler handler = new SynthesizedAnnotationInvocationHandler(attributeExtractor);

		// Can always expose Spring's SynthesizedAnnotation marker since we explicitly check for a
		// synthesizable annotation before (which needs to declare @AliasFor from the same package)
		Class<?>[] exposedInterfaces = new Class<?>[] {annotationType, SynthesizedAnnotation.class};
		return (A) Proxy.newProxyInstance(annotation.getClass().getClassLoader(), exposedInterfaces, handler);
	}
代理类详情查看SynthesizedAnnotationInvocationHandler

在这里插入图片描述
在这里插入图片描述

注释的源码

从 AnnotationUtils.findAnnotation(getClass(), ContextConfiguration.class);开始

	@Nullable
	public static <A extends Annotation> A findAnnotation(Class<?> clazz, Class<A> annotationType) {
		return findAnnotation(clazz, annotationType, true); //默认查询出来的Annotation放到缓存里面去
	}

findAnnotation(clazz, annotationType, true);

	@SuppressWarnings("unchecked")
	@Nullable
	private static <A extends Annotation> A findAnnotation(
			Class<?> clazz, @Nullable Class<A> annotationType, boolean synthesize) {
	    //Class 不能够为null
		Assert.notNull(clazz, "Class must not be null");
		//注解不能够为NULL 
		if (annotationType == null) {
			return null;
		}
		//调用内部类  AnnotationCacheKey  放到缓存里面去
		AnnotationCacheKey cacheKey = new AnnotationCacheKey(clazz, annotationType);
		//通过内部类生成cacheKey 先从缓存里面获取,第一次肯定没有
		A result = (A) findAnnotationCache.get(cacheKey);
		if (result == null) {
		    //缓存里面没有 那么从类上获取注解
			result = findAnnotation(clazz, annotationType, new HashSet<>());
			//如果查找到了,并且synthesize(缓存标志位) 为true  那么放到缓存里面去
			if (result != null && synthesize) {
				result = synthesizeAnnotation(result, clazz);
				findAnnotationCache.put(cacheKey, result);
			}
		}
		return result;
	}

涉及到的调用方法
findAnnotation(Class<?> clazz, Class annotationType, Set visited)

	@Nullable
	private static <A extends Annotation> A findAnnotation(Class<?> clazz, Class<A> annotationType, Set<Annotation> visited) {
		try {
		    //如果这样的注释 直接存在 ,则返回指定类型的元素注释,否则返回null。 
			A annotation = clazz.getDeclaredAnnotation(annotationType);
			if (annotation != null) {
				return annotation;
			}
			//该类上不直接存在这个注解,
			for (Annotation declaredAnn : getDeclaredAnnotations(clazz)) {
				Class<? extends Annotation> declaredType = declaredAnn.annotationType();
				//不是java.lang 包下的注解  就添加到这个set里面去
				if (!isInJavaLangAnnotationPackage(declaredType) && visited.add(declaredAnn)) {
				    //递归查找注解,直到找到返回
					annotation = findAnnotation(declaredType, annotationType, visited);
					if (annotation != null) {
						return annotation;
					}
				}
			}
		}
		catch (Throwable ex) {
		    // 如果ex是AnnotationConfigurationException的实例   包装成AnnotationConfigurationException  重新抛出,其他的则打印日志
			handleIntrospectionFailure(clazz, ex);
			return null;
		}
		//类/字段/方法/构造函数从getDeclaredAnnotations都找不到的时候 从接口中查找
		for (Class<?> ifc : clazz.getInterfaces()) {
			A annotation = findAnnotation(ifc, annotationType, visited);
			if (annotation != null) {
				return annotation;
			}
		}
		//接口差找不到的时候  从 父类上继续走这个步骤 ,直到找到或者 为顶级父类
		Class<?> superclass = clazz.getSuperclass();
		if (superclass == null || superclass == Object.class) {
			return null;
		}
		return findAnnotation(superclass, annotationType, visited);
	}

getDeclaredAnnotations(AnnotatedElement element)

	static Annotation[] getDeclaredAnnotations(AnnotatedElement element) {
		if (element instanceof Class || element instanceof Member) {
			// Class/Field/Method/Constructor returns a defensively cloned array from getDeclaredAnnotations.
			// Since we use our result for internal iteration purposes only, it's safe to use a shared copy.
		  //类/字段/方法/构造函数从getDeclaredAnnotations返回一个防御性克隆的数组。
		  //因为我们只将结果用于内部迭代,所以使用共享副本是安全的。
			return declaredAnnotationsCache.computeIfAbsent(element, AnnotatedElement::getDeclaredAnnotations);
		}
		// 如果这样的注释 直接存在 ,则返回指定类型的元素注释,否则返回null。 
		return element.getDeclaredAnnotations();
	}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值