最近在研究@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();
}