记得第一次接触到Lombok是拉一个新项目时,用IDEA打开都是一片红的,第一印象是不太好的。不过后面整个团队都用起来之后也还不错的。说节省了时间吧,在使用中好像也没什么感觉,有点像空格和tab一样,都是一下子的事,可能是习惯问题吧。回到主题,比起争论lombok的使用与否,更加好奇它实现的过程。
APT全称是Pluggable Annotation Processing API(可插入注释处理API),是JSR269规范提供的一套API,可以在编译期自定义我们期望的编译输出,APT并不能修改已存在的源码,它只能添加新源码,帮我们做一些检查代码,生成模板化代码或者配置文件等。我们常见的应用有Lombok,yml文件ctrl+鼠标左键定位到具体文件(注解处理器生成spring-configuration-metadata.json),google的AutoService(下文会介绍)等.
从Javac代码的总体结构来看,编译过程大致可以分为1个准备过程和3个处理过程,它们分别如下 所示。
- 准备过程:初始化插入式注解处理器。
- 解析与填充符号表过程,包括词法、语法分析。将源代码的字符流转变为标记集合,构造出抽象语法树,填充符号表。产生符号地址和符号信息。
- 插入式注解处理器的注解处理过程。
- 分析与字节码生成过程,包括标注检查、数据流及控制流分析、解语法糖、字节码生成。
如果这些插件在处理注解期间对语法树进行了修改,编译器将回到解析及填充符号表的过程重新处理,直到所有插入式注解处理器都没有再对语法树进行修改为止,每一次循环称为一个Round,也就是上图的回环过程
把上述处理过程对应到代码中,Javac编译动作的入口是 com.sun.tools.javac.main.JavaCompiler类,上述3个过程的代码逻辑集中在这个类的compile()和compile2()方法里,整个编译过程主要的处理由下图中标注的8个方法来完成
创建一个maven项目,引入相关jar包和设置maven-compiler-plugin,关于为什么要设置proc:none可以看Maven annotation processing processor not found
1.目录树
2.创建Getter、Setter注解
3.创建Getter、Setter对应的注解处理器
Settter注解处理器和Getter的大同小异,只是生成set方法的步骤不太一样,详细可查看openjdk-7 TreeMaker
4.创建测试Class
5.运行
直接运行肯定会报错的,因为实际上这应该是分开两个工程的,一个是注解处理器工程,一个是业务工程。我们需要用已经编译好的注解处理器工程在编译期去处理其他的工程,一起编译的话肯定会出错嘛,按照这个思路写成shell脚本如下:
可以清楚的看到,执行脚本之后可以正常的运行了,正确打印yk
6.打包(SPI机制)
SPI全称为(Service Provider Interface) ,是JDK内置的一种服务提供发现机制;主要被框架的开发人员使用,比如java.sql.Driver接口,数据库厂商实现此接口即可,当然要想让系统知道具体实现类的存在,还需要使用固定的存放规则,需要在resources下的META-INF/services/目录里创建一个以服务接口命名的文件,这个文件里的内容就是这个接口的具体的实现类
打包的操作比较简单,java有一个SPI机制,包括JDBC,Spring,Dubbo都有大量使用。比如大家熟悉的例子,可以看Mysql连接的jar包,对应的目录下就有
我们在resources目录下创建一个META-INF文件夹,再在下面创建一个service文件夹,最后创建一个名为javax.annotation.processing.Processor的文件之后,在这个文件里面写上全限定名的实现类即可,多个实现类的话按enter分行填写就行了
打包前把测试用的那个类注释一下,否则编译会报错
打包:clean->complie->package->install
1.新建maven项目并引入依赖
2.创建并运行Demo
直接运行即可,结果如图
AutoService的github,readme就有教程
1.删除MATE-INF文件夹、修改pom文件
删除我们上文中创建的MATE-INF文件夹
添加对应的依赖,以及修改一下maven的编译插件
2.添加autoService注解
在SetterProcessor和getterProcessor类上都添加@AutoService(Processor.class)
3.打包
正常的clean->complie->package->install即可
我们看看编译输出,实际上也是通过注解处理器帮我们自动生成这么的一个文件
这篇文章终于摸出来了,写这篇文章的时候了解到了许多知识点,还包括了以前没接触过编译方面的知识,查看了很多技术大佬的文章,也粗看了一遍《深入理解Java虚拟机》里面的相关篇章,收益匪浅。
以上。
Lombok原理分析与功能实现
Java-JSR-269-插入式注解处理器
JVM系列六(自定义插入式注解器)
javac命令初窥
java注解处理器——在编译期修改语法树
《深入理解Java虚拟机:JVM高级特性与**实践(第3版)周志明》
版权声明:
本文来源网络,所有图片文章版权属于原作者,如有侵权,联系删除。
本文网址:https://www.bianchenghao6.com/java-jiao-cheng/7739.html