Java注解

1. 注解入门

1.1 Annotation

  • 位于源码中(代码/注释/注解),使用其他工具进行处理的标签
  • 注解用来修饰程序的元素,但不会对被修饰的对象有直接的影响
  • 只有通过某种配套的工具才会对注解信息进行访问和处理
  • 主要用途
    • 提供信息给编译器/IDE工具
    • 可用于其他工具来产生额外的代码/配置文件等
    • 有一些注解可在程序运行时访问,增加程序的动态性

1.2 JDK预定义的普通注释(部分)

  • @Override 表示继承和改写
  • @Deprecated 表示废弃
  • @SuppressWarnings 表示压制告警
  • @SafeVarags 不会对不定项参数做危险操作
  • @FunctionInterface 声明功能性接口

1.3 JDK预定义的元注解(部分)

元注解:修饰注解的注解

  • @Target 设置目标范围
  • @Retention 设置保持性
    • RetentionPolicy.SOURCE 注解仅存在源码,不在class文件
    • RetentionPolicy.CLASS 默认的注解保留策略,注解存在于class文件,但是不能被JVM加载
    • RetentionPolicy.RUNTIME 注解可以被JVM运行时访问到,通常情况下,可以结合反射来做一些事情
  • @Documented 文档 (指明这个注解可以被Javadoc工具解析,形成帮助文档)
  • @Inherited 注解继承 (让一个类和它的子类都包含某个注解,普通的注解没有继承功能)
  • @Repeatable 此注解可以重复修饰

1.4 自定义注解

  • 注解可以包括的类型
    • 8种基本类型(int/short/long/float/double/byte/char/boolean)
    • String
    • Class
    • enum类型
    • 注解类型
    • 由前面类别组成的数组
  • 自定义注解
    • 扩展于java.lang.annotaion.Annotation
    • 成员可以包括多种类型
    • 使用时可以给注解成员赋值
    • 用于修饰多种程序元素

2. 注解的解析

2.1 生命周期

  • RetentionPolicy.RUNTIME注解采用反射进行解析
  • RetentionPolicy.CLASS注解采用专用的字节码工具进行解析
  • RetentionPolicy.SOURCE注解采用注解处理器进行解析
    • 注解处理器继承AbstractProcessor,重写process方法
    • java -processor Processor1,Proccessor2,... sourceJavaFile

2.1 反射解析RUNTIME注解

image-20220822225709343

3. RUNTIME注解实现本质

3.1 RUNTIME注解调用路线

  • 注解采用接口中的方法来表示变量
  • Java为注解产生一个代理类,这个代理类包括一个AnnotationInvocationHandler成员变量
  • AnnotationInvocationHandler有一个Map的成员变量,用来存储所有的注解的属性赋值
  • 在程序中,调用注解接口的方法,将会被代理类接管,然后根据方法名字,到Map里面拿相应的Value并返回

3.2 RUNTIME注解的设计思路

  • 传统的接口中的变量,都是public final static

  • 注解需要随意赋值

    • 注解方法表示变量
    • 采用代理类拦截注解方法访问
    • 所有注解的赋值,都放在Map中,访问速度快
  • AnnotationInvocationHandler

    public Object invoke(Object proxy, Method method, Object[] args) {
        String member = method.getName();
        int parameterCount = method.getParameterCount();
        if (parameterCount == 1 && member == "equals" && method.getParameterTypes()[0] == Object.class) {
            return this.equalsImpl(proxy, args[0]);
        } else if (parameterCount != 0) {
            throw new AssertionError("Too many parameters for an annotation method");
        } else if (member == "toString") {
            return this.toStringImpl();
        } else if (member == "hashCode") {
            return this.hashCodeImpl();
        } else if (member == "annotationType") {
            return this.type;
        } else {
            Object result = this.memberValues.get(member);
            if (result == null) {
                throw new IncompleteAnnotationException(this.type, member);
            } else if (result instanceof ExceptionProxy) {
                throw ((ExceptionProxy)result).generateException();
            } else {
                if (result.getClass().isArray() && Array.getLength(result) != 0) {
                    result = this.cloneArray(result);
                }
    
                return result;
            }
        }
    }
    
posted @ 2022-08-21 23:08  hunter-w  阅读(48)  评论(1编辑  收藏  举报