1. 前言
Java 源码中应用 Lombok 的 @Data 注解:
编译后的 class 文件,主动增加了一些办法
在编译期为代码进行了加强,如何做了加强,为什么会这样?
2. 编译器在编译期间做的操作
咱们都晓得 @Data 注解,@Retention(RetentionPolicy.SOURCE),这个的意思是,注解保留的工夫是在源码期间,编译后该注解就会删除,在删除之前,编译器会为其增加一些办法等等操作,即在编译期为代码进行了加强。
3. 原理
3.1JSR-269 提案
在 JDK6 提出并通过了 JSR-269 提案,提案通过了一组被称为“插入式注解处理器”的规范 API,能够提前至编译期对代码中的特定注解进行解决,从而影响到编译器的工作过程。
3.2Java 语言实现
对于底层的一些实现, 广泛会认为实现是像虚拟机一样应用 C ++ 实现, 对于 Java 程序员来说并不是特地敌对。然而 Javac 编译器是应用 Java 实现的,更容易上手。
3.3Javac 的编译过程
Javac 的编译过程大抵分为几步
- 筹备过程: 初始化插入式注解处理器
- 解析与填充符号表过程 词法、语法分析构建形象语法树 (AST)
- 插入式注解处理器的注解处理过程
- 剖析与字节码生成过程
- 语法树变动后会再次解析与填充符号表, 语法树没有变动时编译器就不会再对源码字符流操作, 而是基于形象语法树
综上所述想实现 Lombok 的成果只须要恪守 JSR-269 在编译期对 AST 进行操作即可实现 当然不止有 Lombok 通过这种形式实现, 例如 FindBug、MapStruct 等也通过这种形式实现
3.4 Lombok 在编译过程中如何做的
Lombok 实质上就是一个实现了“JSR 269 API”的程序。在应用 javac 的过程中,它产生作用的具体流程如下:
- javac 对源代码进行剖析,生成了一棵形象语法树(AST)
- 运行过程中调用实现了“JSR 269 API”的 Lombok 程序
- 此时 Lombok 就对第一步骤失去的 AST 进行解决,找到 @Data 注解所在类对应的语法树(AST),而后批改该语法树(AST),减少 getter 和 setter 办法定义的相应树节点
- javac 应用批改后的形象语法树(AST)生成字节码文件,即给 class 减少新的节点(代码块)
3.5 优缺点
长处:
- 能通过注解的模式主动生成结构器、getter/setter、equals、hashcode、toString 等办法,进步了肯定的开发效率
- 让代码变得简洁,不必过多的去关注相应的办法
- 属性做批改时,也简化了保护为这些属性所生成的 getter/setter 办法等
毛病:
- 不反对多种参数结构器的重载
- 尽管省去了手动创立 getter/setter 办法的麻烦,但大大降低了源代码的可读性和完整性,升高了浏览源代码的舒适度
总结:
- 像 lombok 这种插件,曾经不仅仅是插件了,它在编译器编译时通过操作 AST(形象语法树)扭转字节码生成,变相的说它就是在扭转 java 语法,它扭转了你编写源码的形式,它不像 spring 的依赖注入一样是运行时的个性,而是编译时的个性。如果一个我的项目有十分多这样的插件,会极大的升高浏览源代码的舒适度。
- lombok 只是省去了一些人工生成代码的麻烦,然而这些 getter/setter 等等的办法,用 IDE 的快捷键也可很不便的生成。况且,有时通过给 getter/setter 加一点点业务代码(但通常不倡议这么加),能极大的简化某些业务场景的代码。