在写Java代码的时候,最烦写setter/getter方法,自从有了Lombok插件不用再写那些方法之后,感觉再也回不去了,那你们是否好奇过Lombok是怎么把setter/getter方法给你加上去的呢?有的同学说我们Java引入Lombok之后会污染依赖包,那我们可不可以自己写一个工具来代替Lombok呢?,序言提到的问题其实都是同一个问题,就是如何去获取和修改Java源代码?,要回答这个问题,我们需要回答这几个问题:,希望大家看完本文能够自己写一个简易的Lombok工具。,如何解析源代码,其实从我们的代码到被编译,中间隔了一个数据结构,叫做AST(抽象树)。具体的形式,可以查看下面的图片。右边的便是AST的数据结构了。,,代码编译都有哪些步骤,整个编译过程大致如下:,,图片来自 openjdk,1、初始化插入注解处理器,2、解析与填充符号表过程,a.词法分析、语法分析。将源代码的字符流转变为标记集合,构造出抽象语法树。,b.填充符号表。产生符号地址和符号信息。,3、插入式注解处理器的注解处理过程:插入式注解处理器的执行阶段。后面我会给大家带来两个此方面的实用实战例子。,4、分析与字节码生成过程,a.标注检查。对语法的静态信息检查。,b.数据流及控制流分析。对程序动态运行过程进行检查。,c.解语法糖。将简化代码编写的语法糖还原为原有的形式。,d.字节码生成。将前面各个步骤所生成的信息转化成为字节码。,我们知道了上面的理论之后,接下来我们进行实战。带着大家一起去修改AST(抽象树)。添加自己的代码。,如何自己实现一个自动添加Setter/Getter的工具,首先,我们创建一个自己的注解。,创建一个需要生成setter/getter方法的实体类,接下来就来看一看如何来生成我们想要的字符串。,整体代码如下:,代码有点多,我们逐一拆解说明:,下面这是整个代码结构的脑图,后面的讲解会基于这个顺序。,,a. 注解,@SupportedAnnotationTypes 表示我们需要监听的注解,比如我们之前定义的 @MySetterGetter。,@SupportedSourceVersion 表示我们想要对什么版本的Java源代码进行处理。,b. 父类,AbstractProcessor是本次的核心类,编译器在编译的时候会扫描此类的子类。其中有一个子类必须实现的核心方法 public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv),此方法如果是返回为true就说明编译的那个类抽象树的结构又变化,需要重新进行词法分析和语法分析(可以查看上面提到的那个编译流程图)。如果返回的是false就说明没有变化。,c. process方法,主要的操作逻辑是:,1、拿到所有被我们MySetterGetter标注的类。,2、遍历所有的类,生成类的抽象树结构。,3、对类进行操作:,a.找到类中所有的变量。,b.对变量进行生成Set和Get方法。,4、返回 true,说明类结构变了,需要重新解析。如果是false说明没有变,不用重新解析。,d. 操作JCTree树,主要是在操作抽象树,可以查看文末附件中的文章进行学习。,e. 方法名称拼接,这一块儿和字符串拼接没啥区别,用过反射的同学应该也都清楚这个操作了。,到此为止,我们就已经介绍完了Lombok的原理。怎么样是不是很简单。接下来,就让我们把它运行起来,投入到实战之中。,f. 运行,最后来看一下如何正确的运行这个我们写的工具。,1.环境,我的系统环境是 macOs Monterey;,java版本是,2.编译processor,在你存放 MySetterGetter 和 MySetterGetterProcessor 两个类的目录下进行编译。,执行成功后会出现这三个class文件。,,3.声明插入式注解处理器,,com.study.practice.nameChecker.MySetterGetterProcessor,4.用我们的工具去编译目标类,比如我们本次是要编译那个test.java。,它的内容再回顾一下:,然后我们就去编译它(注意类前面的路径。这个你们得换成自己的工程目录。),执行之后如果没有修改我的代码的话会打印这几个字符串:,最后会生成Test.class文件。,,5.成果,最后的class文件解析出来就是这个样子的。如下图所示:,,看到Setter/Getter方法就说明我们已经大功告成了!是不是很简单。,到此为止,我们就学会了如何自己写一个属于自己的简易Lombok的插件了。,附件,treemarker 的介绍:,http://www.docjar.com/docs/api/com/sun/tools/javac/tree/TreeMaker.html
© 版权声明
文章版权归作者所有,未经允许请勿转载。