@Data
注解是Lombok库中的一个非常有用的注解,它简化了Java类的编写。使用这个注解后,Lombok会在编译时自动为你的类生成常见的方法,比如getter、setter、toString、equals和hashCode等。
@Data
注解底层实现原理
-
Annotation Processing:
- Lombok使用Java的注解处理器(Annotation Processor)机制,这个机制在编译期间扫描源码中使用的Lombok注解。
-
AST(抽象语法树)修改:
- 在编译过程中,Lombok通过修改抽象语法树(AST),将其插入到Java编译器的流程中。在解析源代码阶段,通过访问和修改这些树,Lombok添加必要的方法。
-
字节码生成:
- 修改后的AST被用来生成字节码。因此,编译后的.class文件包含完整的getter、setter等方法,即使源码中没有显式地定义它们。
-
处理器配置:
- Lombok的核心是
lombok.jar
,内含多个注解处理器。这些处理器根据不同的注解操作类的结构。
- Lombok的核心是
要深入理解Lombok的底层源码实现逻辑,我们可以通过一个简单案例,比如@Getter
注解,来分析它是如何工作的。
案例:@Getter
注解
假设我们有以下Java类:
java
代码解读
复制代码
import lombok.Getter; public class User { @Getter private String name; }
使用@Getter
后,编译时将自动为name
字段生成一个getter方法。下面是@Getter
实现的基本步骤:
整理了一份好像面试笔记包括了:Java面试、Spring、JVM、MyBatis、Redis、MySQL、并发编程、微服务、Linux、Springboot、SpringCloud、MQ、Kafka 面试专题
需要全套面试笔记【点击此处即可】免费获取
源码处理步骤
-
注解扫描:
- Lombok的注解处理器会扫描Java源代码,发现
@Getter
注解以及它所标注的字段。
- Lombok的注解处理器会扫描Java源代码,发现
-
AST访问和修改:
- Lombok在编译期间访问Java编译器生成的AST。对于每一个使用
@Getter
的字段,查找其所在的类节点。
- Lombok在编译期间访问Java编译器生成的AST。对于每一个使用
-
方法生成:
- 在AST中,Lombok为该字段插入一个
getName()
方法节点。这通常涉及创建一个新的方法节点,并将其添加到类节点的子节点列表中。
- 在AST中,Lombok为该字段插入一个
-
字节码生成:
- 修改后的AST用于生成最终的字节码,因此编译出的
.class
文件包含完整的方法实现。
- 修改后的AST用于生成最终的字节码,因此编译出的
具体源码分析
-
Annotation Processor:
LombokProcessor
是核心入口,负责管理所有Lombok注解的处理。
-
Handler Class:
HandleGetter
类负责@Getter
注解的具体逻辑。在这个类中,通过调用JavacTreeMaker
等工具类来创建新的AST节点。
-
Node Addition:
- 使用诸如
maker.MethodDef()
这样的API来定义方法签名,然后通过树操作将新节点加入原有的类结构。
- 使用诸如
实现逻辑概述
-
识别阶段:
- Lombok初始化时注册各个注解的处理器。
@Getter
处理器被触发时,遍历类中的字段,识别带有@Getter
注解的字段。
- Lombok初始化时注册各个注解的处理器。
-
逻辑应用:
- 对于每个匹配的字段,构建相应的getter方法节点。设置方法的返回类型、方法体(通常是返回字段值)和访问修饰符。
-
AST更新:
- 将新创建的getter方法节点插入到类的AST中,确保其他注解处理器或编译器能正确识别和使用这些新方法。
思考题:使用@Data注解和手动编写代码实现Getter方法性能差别大吗
在使用@Data
注解和手动编写getter方法之间,性能上的差别实际上非常小甚至可以忽略不计。原因如下:
-
编译时处理:
- Lombok的
@Data
注解是在编译时通过注解处理器生成实际的字节码
。当你查看编译后的.class
文件时,无论是使用Lombok还是手动编写,生成的字节码几乎是一样的。
- Lombok的
-
运行时效率:
- 因为最终生成的字节码相同,运行时的性能是相同的。JVM执行的是字节码,因此无论是手动编写还是使用Lombok生成的方法,执行效率没有区别。
-
开发者效率:
- 使用Lombok的优势在于提高了开发效率,减少了样板代码,并降低了出错的风险。这对生产力和代码可维护性有显著的提升。
-
代码可读性和简洁性:
- Lombok让代码更为简洁和易读,没有多余的getter和setter方法占用空间,这使得类结构更清晰。