Java编译期注解处理器(APT)在编译阶段扫描注解并生成源文件,运行时零开销,核心通过javax.annotation.processing实现,需定义SOURCE保留策略注解、继承AbstractProcessor、用Filer生成代码,并在META-INF/services中注册;注意仅能读取源码信息、不可修改原类、需用JavaPoet等工具安全生成代码。

Java 中通过 编译期注解处理器(Annotation Processor),可以在编译阶段扫描特定注解,并自动生成 Java 源文件或资源文件。这种方式不修改原有类,也不依赖反射,生成的代码在编译期就存在,运行时零开销,常用于 ButterKnife、Dagger、Lombok(部分能力)、Room 等框架。
核心机制:APT(Annotation Processing Tool)
从 JDK 6 开始,Java 提供了标准的注解处理 API(javax.annotation.processing),编译器(如 javac)会在编译过程中调用注册的 Processor 实现类。它分两步执行:
- 发现并收集所有被标记的元素(类、方法、字段等)及其注解信息;
- 调用
Filer创建新的 .java 文件(或辅助资源),交由后续编译阶段处理。
实现一个简单注解 + 处理器的步骤
以生成「根据注解自动生成 Builder 类」为例:
-
定义注解:必须声明
@Retention(RetentionPolicy.SOURCE)(仅保留到源码期)和@Target(ElementType.TYPE)(作用于类); -
编写 Processor:继承
AbstractProcessor,重写process()方法,在其中遍历RoundEnvironment获取被注解的Element; -
生成代码:用
Filer.createSourceFile()创建新源文件,配合字符串拼接或模板引擎(如 JavaPoet)写出合法 Java 代码; -
注册处理器:在
resources/META-INF/services/javax.annotation.processing.Processor中写入处理器全限定名。
关键细节与注意事项
实际开发中容易踩坑的地方:
立即学习“Java免费学习笔记(深入)”;
- 注解处理器运行在独立的 round 中,不能访问已生成字节码,只能读取源码级信息(如类型名、方法签名),无法获取泛型实际类型参数(需用
TypeMirror和TypeUtils推导); - 不能在
process()中修改已有类结构(如添加方法),只能新建文件; - 多个处理器之间无执行顺序保证,若需依赖,应使用
@SupportedOptions或模块化隔离; - Maven/Gradle 需显式配置 annotationProcessor 依赖(如 Gradle 的
annotationProcessor 'group:artifact:version'),否则不会触发处理流程。
推荐工具:JavaPoet 让代码生成更安全
手动拼接字符串易出错且难维护。Square 开源的 JavaPoet 可以用声明式 API 构建语法树:
- 支持 MethodSpec、TypeSpec、FieldSpec 等对象描述结构;
- 自动处理缩进、分号、import 导入、重名类去重;
- 与 APT 集成自然,例如:
JavaFile.builder("com.example", typeSpec).build().writeTo(filer)。


















