编译期注解处理器(Annotation Processor)是Java在javac编译阶段自动扫描、解析并处理注解的工具,用于生成新源文件或资源、校验代码,不改变运行时行为;其核心是继承AbstractProcessor,重写process()方法,配合@SupportedAnnotationTypes和@SupportedSourceVersion声明支持范围,并通过Filer生成代码、Messager报告信息。

什么是编译期注解处理器
编译期注解处理器(Annotation Processor)是在 Java 源码编译阶段(javac 过程中)自动扫描、解析并处理特定注解的工具。它不改变运行时行为,而是生成新源文件(如 .java)、资源文件或报告错误。核心类是 javax.annotation.processing.AbstractProcessor,需配合 @SupportedAnnotationTypes 和 @SupportedSourceVersion 声明支持范围。
编写一个基础注解处理器
以自动生成简单 Builder 类为例:
- 定义一个标记注解,比如
@AutoBuilder,加在目标类上 - 新建处理器类继承
AbstractProcessor - 重写
getSupportedAnnotationTypes()或用注解声明支持的注解类型 - 重写
process():获取被注解的元素、生成代码、用Filer写入新文件
示例片段:
@SupportedAnnotationTypes("com.example.AutoBuilder")
@SupportedSourceVersion(SourceVersion.RELEASE_8)
public class AutoBuilderProcessor extends AbstractProcessor {
private Messager messager;
private Filer filer;
<pre class="brush:php;toolbar:false;">@Override
public synchronized void init(ProcessingEnvironment processingEnv) {
super.init(processingEnv);
this.messager = processingEnv.getMessager();
this.filer = processingEnv.getFiler();
}
@Override
public boolean process(Set extends TypeElement> annotations, RoundEnvironment roundEnv) {
for (Element element : roundEnv.getElementsAnnotatedWith(AutoBuilder.class)) {
if (element.getKind() == ElementKind.CLASS) {
TypeElement typeElement = (TypeElement) element;
String className = typeElement.getSimpleName().toString();
String packageName = processingEnv.getElementUtils()
.getPackageOf(typeElement).getQualifiedName().toString();
try {
JavaFileObject file = filer.createSourceFile(
packageName + "." + className + "Builder");
try (Writer writer = file.openWriter()) {
writer.write("public class " + className + "Builder { /* ... */ }");
}
} catch (IOException e) {
messager.printMessage(Diagnostic.Kind.ERROR,
"Cannot generate Builder for " + className, element);
}
}
}
return true; // 表示已处理,后续 processor 不再处理该注解
}}
Java项目代码review工具。分析Git变更+完整调用链路上下文,推断业务需求,进行多维度评分和分类汇总,生成完整PRD文档。包含细粒度Java代码审查清单(Null安全、异常处理、Streams、并发、equals/hashCode、资源管理、API设计、性能、MyBatis/ORM、事务边界、SQL/DD...
配置和启用注解处理器
注解处理器不能直接运行,必须让 javac 在编译时加载它:
-
Maven 项目:在
pom.xml中添加maven-compiler-plugin配置,并通过<annotationprocessorpaths></annotationprocessorpaths>引入处理器模块(或使用<compilerargs></compilerargs>手动指定) -
Gradle 项目:用
annotationProcessor依赖声明(Java Plugin 下)或compileOnly+ 显式注册 -
手动 javac:用
-processorpath指定处理器 JAR,用-processor指定全限定类名,例如:javac -processorpath my-processor.jar -processor com.example.AutoBuilderProcessor *.java - 确保处理器 JAR 的
META-INF/services/javax.annotation.processing.Processor文件存在,内容为处理器类全名(换行结尾),否则 javac 无法自动发现
关键注意事项和技巧
实际开发中容易踩坑,注意以下几点:
-
process()方法中禁止修改已有源码(如反射改 AST),只能读取和生成;否则违反 JSR 269 规范 - 用
Messager输出日志或错误,不要用System.out—— IDE 和构建工具依赖它做高亮和定位 - 避免在
process()中调用Element.toString()或TypeMirror.toString()获取语义名,应使用Elements.getBinaryName()或Types.erasure()等 API - 若需跨 round 处理(如先生成类 A,再在下一轮处理类 A 上的注解),返回
false并在下次 round 中继续处理 - 推荐搭配
javapoet库生成 Java 源码,比字符串拼接更安全、可维护
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










