Java注解总结

元注解的源码结构

@Document
@Inherited
@Retention
@Target

@Native
@Repeatable

其中前4个是元注解

元注解负责注解自定义注解 自定义注必须使用元注解

元注解的用途
@Target
	标识注解的使用范围 可以赋值为ElementType类型 ElementType定义如下
public enum ElementType {
    TYPE,
    FIELD,
    METHOD,
    PARAMETER,
    CONSTRUCTOR,
    LOCAL_VARIABLE,
    ANNOTATION_TYPE,
    PACKAGE,
    TYPE_PARAMETER,
    TYPE_USE
}

public enum RetentionPolicy {
    SOURCE,
    CLASS,
    RUNTIME
}

RetentionPolicy.SOURCE 表明注解会被编译器丢弃 字节码中不会带有注解信息
RetentionPolicy.CLASS 表明注解会被写入字节码文件 且是@Retention的默认值
RetentionPolicy.RUNTIME 表明注解会被写入字节码文件 并且能够被JVM在运行时获取到 可以通过反射的方式解析到
@Documented

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Documented {
}

jdk中是通过AnnotatedElement(package java.lang.reflect)接口实现对注解的解析 我们的Class类实现了AnnotatedElement接口
public final class Class<T> implements java.io.Serializable,
                              GenericDeclaration,
                              Type,
                              AnnotatedElement {
  ......
}
AnnotatedElement的注释:
Represents an annotated element of the program currently running in this VM.  This interface allows annotations to be read reflectively
翻译过来就是:AnnotatedElement代表了jvm中一个正在运行的被注解元素,这个接口允许通过反射的方式读取注解
可以看下Class类中对于AnnotatedElement接口都是如何实现的:
    /**
     * @throws NullPointerException {@inheritDoc}
     * @since 1.5
     */
    @SuppressWarnings("unchecked")
    public <A extends Annotation> A getAnnotation(Class<A> annotationClass) {
        Objects.requireNonNull(annotationClass);

        return (A) annotationData().annotations.get(annotationClass);
    }
    
    @Override
    public boolean isAnnotationPresent(Class<? extends Annotation> annotationClass) {
        return GenericDeclaration.super.isAnnotationPresent(annotationClass);
    }

	@Override
    public <A extends Annotation> A[] getAnnotationsByType(Class<A> annotationClass) {
        Objects.requireNonNull(annotationClass);

        AnnotationData annotationData = annotationData();
  return AnnotationSupport.getAssociatedAnnotations(annotationData.declaredAnnotations,this,annotationClass);
    }
	
	 public Annotation[] getAnnotations() {
        return AnnotationParser.toArray(annotationData().annotations);
    }

    @Override
    @SuppressWarnings("unchecked")
    public <A extends Annotation> A getDeclaredAnnotation(Class<A> annotationClass) {
        Objects.requireNonNull(annotationClass);

        return (A) annotationData().declaredAnnotations.get(annotationClass);
    }

    @Override
    public <A extends Annotation> A[] getDeclaredAnnotationsByType(Class<A> annotationClass) {
        Objects.requireNonNull(annotationClass);

        return AnnotationSupport.getDirectlyAndIndirectlyPresent(annotationData().declaredAnnotations,
                                                                 annotationClass);
    }

    public Annotation[] getDeclaredAnnotations()  {
        return AnnotationParser.toArray(annotationData().declaredAnnotations);
    }

上面的接口实现中 大致的原理都是一致的 挑选其中的getAnnotation方法来讲解

getAnnotation
根据注解的class实例从类的注解缓存数据中获取匹配的注解类型
Controller是注解类型,Controller.getClass()获取到的就是Class实例
1、代码中annotationData().annotations是一个Map(key为注解的Class实例,value为注解类型) 源码为

    private static class AnnotationData {
        final Map<Class<? extends Annotation>, Annotation> annotations;
        final Map<Class<? extends Annotation>, Annotation> declaredAnnotations;

        final int redefinedCount;

        AnnotationData(Map<Class<? extends Annotation>, Annotation> annotations,
              Map<Class<? extends Annotation>, Annotation> declaredAnnotations,
			int redefinedCount) {
            this.annotations = annotations;
            this.declaredAnnotations = declaredAnnotations;
            this.redefinedCount = redefinedCount;
        }
    }

2annotationData()的源码是
    private AnnotationData annotationData() {
        while (true) { // retry loop
            AnnotationData annotationData = this.annotationData;
            int classRedefinedCount = this.classRedefinedCount;
            if (annotationData != null &&
                annotationData.redefinedCount == classRedefinedCount) {
                return annotationData;
            }
            // null or stale annotationData -> optimistically create new instance
            AnnotationData newAnnotationData = createAnnotationData(classRedefinedCount);
            // try to install it
            if (Atomic.casAnnotationData(this, annotationData, newAnnotationData)) {
                // successfully installed new AnnotationData
                return newAnnotationData;
            }
        }
    }

核心的逻辑是:当this.annotationData为空,解析类中的annotationData并写入this.annotationData,最后都会返回this.annotationData
3、其中Atomic.casAnnotationData(this, annotationData, newAnnotationData)的作用便是将解析到的annotationData写入this.annotationData:
        static <T> boolean casAnnotationData(Class<?> clazz,
                                             AnnotationData oldData,
                                             AnnotationData newData) {
            return unsafe.compareAndSwapObject(clazz, annotationDataOffset, oldData, newData);
        }

其中unsafe.compareAndSwapObject是一个native方法
4、而createAnnotationData(classRedefinedCount)的作用是解析类中用到的annotationData
    private AnnotationData createAnnotationData(int classRedefinedCount) {
        Map<Class<? extends Annotation>, Annotation> declaredAnnotations =
            AnnotationParser.parseAnnotations(getRawAnnotations(), getConstantPool(), this);
        Class<?> superClass = getSuperclass();
        Map<Class<? extends Annotation>, Annotation> annotations = null;
        if (superClass != null) {
            Map<Class<? extends Annotation>, Annotation> superAnnotations =
                superClass.annotationData().annotations;
            for (Map.Entry<Class<? extends Annotation>, Annotation> e : superAnnotations.entrySet()) {
                Class<? extends Annotation> annotationClass = e.getKey();
                if (AnnotationType.getInstance(annotationClass).isInherited()) {
                    if (annotations == null) { // lazy construction
                        annotations = new LinkedHashMap<>((Math.max(
                                declaredAnnotations.size(),
                                Math.min(12, declaredAnnotations.size() + superAnnotations.size())
                            ) * 4 + 2) / 3
                        );
                    }
                    annotations.put(annotationClass, e.getValue());
                }
            }
        }
        if (annotations == null) {
            // no inherited annotations -> share the Map with declaredAnnotations
            annotations = declaredAnnotations;
        } else {
            // at least one inherited annotation -> declared may override inherited
            annotations.putAll(declaredAnnotations);
        }
        return new AnnotationData(annotations, declaredAnnotations, classRedefinedCount);
    }

整个的处理逻辑是:
1 获取类本身的declaredAnnotations
2 获取父类的annotations
3 将declaredAnnotations+annotations整合 返回
Annotation解析的范例代码:
	@Component
	public class SSHClient {
		。。。
	}

public class AnnotationHelper {

    public static void main(String[] args) {
        Annotation[] annotations = new Annotation[0];

        annotations = SSHClient.class.getAnnotations();

        for (Annotation annotation : annotations) {
            System.out.println(annotation.toString());
            System.out.println(annotation.annotationType());
            System.out.println(annotation.getClass().getName());
            System.out.println(annotation.getClass().getTypeName());
            System.out.println(annotation.getClass().toString());
        }

        if (SSHClient.class.isAnnotationPresent(Component.class)) {
            System.out.println("find Component annotation");
        }

        Annotation annotation = SSHClient.class.getAnnotation(Component.class);

        System.out.println(annotation.toString());
        System.out.println(annotation.annotationType());
        System.out.println(annotation.getClass().getName());
        System.out.println(annotation.getClass().getTypeName());
        System.out.println(annotation.getClass().toString());
    }
}

原文 https://www.jianshu.com/p/e9329c8a59c2

转载于:https://www.cnblogs.com/setlilei/p/10629466.html

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值