lombok通过jsr 269注解处理机制,在编译期利用javac私有api修改ast,自动生成getter、setter等代码并写入.class文件,运行时无需lombok依赖,与手写代码完全一致。

Java 注解本身不会自动生成代码,Lombok 的“魔法”并非靠运行时注解实现,而是利用了 Java 编译器的 Annotation Processing Tool(APT)机制,在编译期(.java → .class 阶段)修改抽象语法树(AST),从而插入 getter、setter、构造器等字节码逻辑。
编译期注解处理(JSR 269)是核心
Lombok 不是靠 @Retention(RUNTIME) 在运行时反射生成代码,而是实现了 javax.annotation.processing.Processor 接口,在 javac 编译过程中介入:
- javac 加载 Lombok 的 processor(通过
META-INF/services/javax.annotation.processing.Processor声明) - 当检测到
@Getter、@Data等注解时,Lombok 的 processor 获取当前编译单元的 AST(基于 javac 内部 API,如com.sun.source.tree和com.sun.tools.javac.tree.JCTree) - 直接修改 AST 节点:例如为字段插入对应的 getter 方法节点,再交还给编译器继续后续流程(语义分析、字节码生成)
- 最终生成的 .class 文件里已包含完整方法,和手写无异 —— 运行时完全不依赖 Lombok JAR
为什么不能用标准 APT 自己写 Lombok?
标准 JSR 269 APT 只允许 读取 AST 并生成新源文件(如 ButterKnife、Dagger),不允许修改原始类的 AST。Lombok 能做到修改,是因为它:
- 使用了 javac 的私有 API(如
com.sun.tools.javac包),绕过标准限制 - 通过
-J-Dlombok.agent=true或 javaagent 方式注入字节码增强(早期版本),或更常见的是利用 javac 的-processor参数 + 对编译器内部结构的深度适配 - 不同 JDK 版本需适配不同 javac 内部结构(这也是 Lombok 升级常需同步 JDK 的原因)
替代方案:现代可维护的做法
如果你希望实现类似效果但避免依赖 javac 私有 API,推荐以下路径:
-
使用 Annotation Processor + 生成辅助类:例如为
@AutoValue生成XXX$$AutoValue子类,通过组合/委托模拟行为(无需改原类) - 结合 ByteBuddy / Javassist 在构建期增强字节码:在 javac 之后、打包前,用 Maven/Gradle 插件读取 .class,动态注入方法(如 MapStruct 的 build-time weaving)
- 采用 JDK 14+ 的 Records + sealed classes + pattern matching:减少模板代码需求,从语言层降低对 Lombok 类工具的依赖
IDE 支持是怎么回事?
Lombok 的 getter/setter 在 IDE 中“可见”,不是因为编译器告诉 IDE,而是 Lombok 提供了对应 IDE 的插件(IntelliJ、Eclipse),这些插件:
- 解析同名注解
- 模拟 AST 修改逻辑,在编辑器内动态提供代码补全、跳转、检查
- 与编译器行为保持一致,但纯属 IDE 层面的“欺骗”,不影响实际编译流程
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











