全部学科
Python全栈
python
NodeJS全栈
nodejs
小程序首页
📅 2026-05-11 8 分钟 ✍️ juanwangdev

Java注解处理器

注解处理器(Annotation Processor)在编译期处理注解,实现代码生成、编译检查等功能。

注解处理器原理

注解处理器是javac的工具,在编译阶段扫描和处理注解。可以生成新的Java文件,但不能修改已有文件。

执行时机

Java
编译开始 → 多轮处理 → 编译结束
           ↓
    处理器扫描注解 → 生成新文件 → 再次扫描新生成的文件

实现注解处理器

1. 定义注解

Java
// 保留策略必须是SOURCE或CLASS(运行时不需要)
@Retention(RetentionPolicy.SOURCE)
@Target(ElementType.TYPE)
public @interface Builder {
    String builderClassName() default "";
}

2. 继承AbstractProcessor

Java
@SupportedAnnotationTypes("com.example.Builder")  // 处理的注解
@SupportedSourceVersion(SourceVersion.RELEASE_11)  // Java版本
public class BuilderProcessor extends AbstractProcessor {

    @Override
    public boolean process(Set<? extends TypeElement> annotations,
                          RoundEnvironment roundEnv) {
        // 处理逻辑
        return true;  // 返回true表示已处理
    }
}

3. 完整处理器实现

Java
@SupportedAnnotationTypes("com.example.Builder")
@SupportedSourceVersion(SourceVersion.RELEASE_11)
public class BuilderProcessor extends AbstractProcessor {

    private Filer filer;      // 文件操作工具
    private Messager messager; // 消息输出工具

    @Override
    public synchronized void init(ProcessingEnvironment processingEnv) {
        super.init(processingEnv);
        filer = processingEnv.getFiler();
        messager = processingEnv.getMessager();
    }

    @Override
    public boolean process(Set<? extends TypeElement> annotations,
                          RoundEnvironment roundEnv) {
        // 遍历所有被@Builder标注的元素
        for (TypeElement annotation : annotations) {
            Set<? extends Element> elements = roundEnv.getElementsAnnotatedWith(annotation);

            for (Element element : elements) {
                if (element.getKind() != ElementKind.CLASS) {
                    error(element, "@Builder只能用于类");
                    continue;
                }

                // 处理类
                processClass((TypeElement) element);
            }
        }
        return true;
    }

    private void processClass(TypeElement classElement) {
        String className = classElement.getSimpleName().toString();
        String packageName = getPackageName(classElement);
        String builderClassName = className + "Builder";

        // 生成Builder类代码
        try {
            JavaFileObject file = filer.createSourceFile(
                packageName + "." + builderClassName);
            try (PrintWriter writer = new PrintWriter(file.openWriter())) {
                writer.println("package " + packageName + ";");
                writer.println("public class " + builderClassName + " {");
                writer.println("    // 生成的代码...");
                writer.println("}");
            }
        } catch (IOException e) {
            error(classElement, "生成代码失败: " + e.getMessage());
        }
    }

    private String getPackageName(TypeElement element) {
        Element enclosing = element.getEnclosingElement();
        while (enclosing.getKind() != ElementKind.PACKAGE) {
            enclosing = enclosing.getEnclosingElement();
        }
        return ((PackageElement) enclosing).getQualifiedName().toString();
    }

    private void error(Element element, String message) {
        messager.printMessage(Diagnostic.Kind.ERROR, message, element);
    }
}

注册处理器

方式1:META-INF/services

META-INF/services/javax.annotation.processing.Processor 文件中写入:

XML
com.example.BuilderProcessor
com.example.FactoryProcessor

方式2:@AutoService(推荐)

Java
@AutoService(Processor.class)
@SupportedAnnotationTypes("com.example.Builder")
@SupportedSourceVersion(SourceVersion.RELEASE_11)
public class BuilderProcessor extends AbstractProcessor {
    // ...
}

需要依赖:

Java
<dependency>
    <groupId>com.google.auto.service</groupId>
    <artifactId>auto-service</artifactId>
    <version>1.1.1</version>
</dependency>

Processor核心API

Java
public abstract class AbstractProcessor implements Processor {

    // 初始化,获取处理环境
    public synchronized void init(ProcessingEnvironment processingEnv);

    // 处理注解(核心方法)
    public abstract boolean process(Set<? extends TypeElement> annotations,
                                   RoundEnvironment roundEnv);

    // 支持的注解类型
    public Set<String> getSupportedAnnotationTypes();

    // 支持的Java版本
    public SourceVersion getSupportedSourceVersion();
}

ProcessingEnvironment工具

text
// 文件操作
Filer filer = processingEnv.getFiler();
filer.createSourceFile("com.example.Generated");  // 创建Java文件
filer.createResource(StandardLocation.CLASS_OUTPUT, "", "config.json");

// 消息输出
Messager messager = processingEnv.getMessager();
messager.printMessage(Diagnostic.Kind.ERROR, "错误信息");
messager.printMessage(Diagnostic.Kind.WARNING, "警告信息");
messager.printMessage(Diagnostic.Kind.NOTE, "提示信息");

// 类型工具
Types types = processingEnv.getTypeUtils();
Elements elements = processingEnv.getElementUtils();

// 选项配置
Map<String, String> options = processingEnv.getOptions();

Element体系

text
// 元素类型判断
Element element = ...;
if (element.getKind() == ElementKind.CLASS) {
    TypeElement classElement = (TypeElement) element;
}

// 常见Element类型
ElementKind.CLASS       // 类
ElementKind.INTERFACE    // 接口
ElementKind.FIELD        // 字段
ElementKind.METHOD       // 方法
ElementKind.PARAMETER    // 参数
ElementKind.PACKAGE      // 包

注意事项

处理器生成的文件会被编译,并触发新一轮注解处理

不能修改已有源文件,只能生成新文件

使用 Filer 创建文件,不要直接用 File API

错误信息用 Messager 输出,不要用 System.out

要点总结

  1. 继承 AbstractProcessor 实现 process() 方法
  2. 用 @SupportedAnnotationTypes 指定处理的注解
  3. 通过 META-INF/services 或 @AutoService 注册处理器
  4. 使用 Filer 生成源文件,Messager 输出错误信息
  5. 只能生成新文件,不能修改已有文件

📝 发现内容有误?点击此处直接编辑

← 上一篇 Java构造器反射
下一篇 → Java注解定义
想查看更多题目和详细解析?
小程序提供完整的题库、模拟考试和详细解析
马上就来

长按或扫描二维码,立即体验

扫码体验小程序
马上就来
使用微信扫描二维码
立即体验完整题库