Java注解处理器需实现Processor接口,通过META-INF注册或auto-service简化,用RoundEnvironment获取元素并安全解析,借助Filer或JavaPoet生成源码,注意annotationProcessor依赖、跨模块可见性及多轮处理陷阱。

Java 注解处理器(Annotation Processor)在编译期生成代码,核心是实现 javax.annotation.processing.Processor 接口,并配合 @SupportedAnnotationTypes 和 @SupportedSourceVersion 声明支持的注解与 Java 版本。关键不在于“写个类”,而在于正确注册、识别目标注解、解析元素、生成合法源码文件。
声明处理器并正确注册
注解处理器必须被编译器发现并加载,不能靠手动触发。需在 META-INF/services/javax.annotation.processing.Processor 文件中写入处理器全限定名(如 com.example.MyProcessor)。Maven 项目推荐用 google/auto-service 库自动完成注册:
- 添加依赖:
compileOnly 'com.google.auto.service:auto-service-annotations:1.1.1'和annotationProcessor 'com.google.auto.service:auto-service:1.1.1' - 在处理器类上加
@AutoService(Processor.class),无需手写配置文件 - 确保注解本身用
@Retention(RetentionPolicy.SOURCE),否则不会参与编译期处理
获取被注解的元素并安全提取信息
在 process() 方法中,通过 RoundEnvironment 获取所有匹配注解的 Element。注意:不能直接强转为 TypeElement 或 VariableElement,应先用 element.getKind() 判断类型;访问字段/方法名、类型、注解值时,必须用 element.getSimpleName().toString()、element.asType().toString() 等安全方式——因为 AST 尚未生成完整 Class,反射或 .getClass() 会失败。
当用户要求为 Java 代码添加注释、修改注释、审查注释、整理注释格式,或要求按照代码注释规范处理 Java 文件时,使用本技能。本技能用于统一生成和维护 Java 类注释模板、按 Git 对比 release 判断版本号、补充每行代码上方中文块注释、调整注释空行规则,并保持 Java 文件 UTF-8 无 BOM 编码。典型触发场景包括:补充类注释、更新 @version、检查 @author 来源、整理行尾注释、把注释放到代码上一行、检查注释是否符合规范、构建前检查 Java 注释风格。
- 用
Elements工具类获取包名、父类、接口等元信息 - 用
Types工具类比较类型(如types.isSameType(a, b)),避免字符串比对 - 若需读取注解属性值(尤其是数组、嵌套注解),用
AnnotationMirror+AnnotationValueVisitor安全遍历
用 JavaPoet 或原生 Filer 生成源码文件
生成代码必须通过 Filer 创建 JavaFileObject,不能直接写磁盘文件,否则编译器无法识别和编译新生成的类。推荐使用 JavaPoet(Square 出品)构造结构化代码,它能自动处理缩进、导入、泛型、重复类名冲突等问题:
- 添加依赖:
compileOnly 'com.squareup:javapoet:1.13.0' - 构建
TypeSpec描述类,用MethodSpec描述方法,再通过JavaFile.builder(packageName, typeSpec).build().writeTo(filer)输出 - 若不用第三方库,可用
filer.createSourceFile("com.example.GeneratedClass")获得Writer,但需手动拼接字符串——易出错,不推荐用于复杂逻辑 - 生成的类名必须全局唯一,建议加入哈希或基于原始类名派生(如
OriginalClass$$Proxy)
规避常见陷阱
很多处理器看似运行了却没生成代码,往往卡在以下环节:
-
注解处理器模块未被 annotationProcessor scope 引入:Gradle 中写成
implementation或compileOnly都无效,必须用annotationProcessor(或kaptfor Kotlin) -
跨 module 时注解类不可见:被处理的注解必须在 processor 的 classpath 中,通常需把注解定义放在独立的
-api模块并让 processor 依赖它 -
多次 round 导致重复生成:检查
roundEnv.processingOver(),只在最后一轮生成;或用roundEnv.getRootElements()判定是否首次处理 - 生成的类引用了尚未编译的类:只能引用已存在的类(JDK 类、processor 依赖的类、当前编译单元中已处理完的类),不能引用同一轮中其他待生成的类
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










