目录
1.概述
注解相当于给某些代码贴了个标签。我们:
- 既可以通过注解处理器在编译时解析这些标签,
- 也可以在运行时通过反射解析这些标签。
解析后都会有一系列动作,这些动作就是对标签语义的诠释。
2.注解处理器
可以为 Java 编译器添加编译规则,以插件的形式接入 Java 编译器中,这些插件我们称之为注解处理器(annotation processor)
2.1 实现
2.1.1 编写处理器
- 注解处理器类都需要实现接口Processor
- JDK 提供了一个实现Processor接口的抽象类AbstractProcessor。该抽象类实现了init、getSupportedAnnotationTypes和getSupportedSourceVersion方法。
- 它的子类可以通过@SupportedAnnotationTypes和@SupportedSourceVersion注解来声明所支持的注解类型以及 Java 版本。
2.1.2 注册为 Java 编译器的插件
-
直接使用 javac 命令的-processor参数
javac -cp /CLASSPATH/TO/CheckGetterProcessor -processor bar.CheckGetterProcessor Foo.java
-
将注解处理器编译生成的 class 文件压缩入 jar 包中,并在 jar 包的配置文件中记录该注解处理器的包名及类名,打包时maven配置为不需要引用当前处理器
具体路径及配置文件名为`META-INF/services/javax.annotation.processing.Processor`
<proc>none</proc>
2.2 用途
2.2.1 定义编译规则
这种注解存在源码级别,可以自定义一些规则,例如:必须要存在某些方法等。
2.2.2 修改已有源代码
并不能真正地修改已有源代码。这里指的是修改由 Java 源代码生成的抽象语法树,在其中修改已有树节点或者插入新的树节点,从而使生成的字节码发生变化。
对抽象语法树的修改涉及了 Java 编译器的内部 API,这部分很可能随着版本变更而失效
例如:Lombok,这个项目自定义了一系列注解,并根据注解的内容来修改已有的源代码
2.2.3 生成新的源代码
用注解处理器来生成源代码则比较常用,压力测试 jcstress、JMH 工具都是依赖这种方式来生成测试代码的。
2.3 源码编译过程
Java 源代码的编译过程可分为三个步骤:
- 解析源文件生成抽象语法树,
- 调用已注册的注解处理器,
- 生成字节码。
- 如果在第 2 步中,注解处理器生成了新的源代码,那么 Java 编译器将重复第 1、2 步,直至不再生成新的源代码。