前言
本文隶属于专栏《100个问题搞定Java虚拟机》,该专栏为笔者原创,引用请注明来源,不足和错误之处请在评论区帮忙指出,谢谢!
本专栏目录结构和参考文献请见100个问题搞定Java虚拟机
正文
注解处理器的用途
- 定义编译规则,并检查被编译的源文件。
- 修改已有源代码。
- 生成新的源代码。
其中,第二种涉及了 Java 编译器的内部 API,因此并不推荐。
第三种较为常见,是 OpenJDK 工具 jcstress,以及 JMH 生成测试代码的方式。
Java 源代码的编译过程
Java 源代码的编译过程可分为三个步骤,分别为解析源文件生成抽象语法树,调用已注册的注解处理器,和生成字节码。
Java编译器的工作流程
Java 源代码的编译过程可分为三个步骤:
- 将源文件解析为抽象语法树;
- 调用已注册的注解处理器;
- 生成字节码。
如果在第 2 步调用注解处理器过程中生成了新的源文件,那么编译器将重复第 1、2 步,解析并且处理新生成的源文件。
每次重复我们称之为一轮(Round)。
也就是说,第一轮解析、处理的是输入至编译器中的已有源文件。
如果注解处理器生成了新的源文件,则开始第二轮、第三轮,解析并且处理这些新生成的源文件。
当注解处理器不再生成新的源文件,编译进入最后一轮,并最终进入生成字节码的第 3 步
Lombok 的实现原理
注解处理器可以用来修改已有源代码或者生成源代码。
确切地说,注解处理器并不能真正地修改已有源代码。
这里指的是修改由 Java 源代码生成的抽象语法树,在其中修改已有树节点或者插入新的树节点,从而使生成的字节码发生变化。
对抽象语法树的修改涉及了 Java 编译器的内部 API,这部分很可能随着版本变更而失效。因此,不推荐这种修改方式。
Project Lombok这个项目自定义了一系列注解,并根据注解的内容来修改已有的源代码。
例如它提供了@Getter和@Setter注解,能够为程序自动添加getter以及setter方法。