Java 注解处理器:自定义注解生成代码指南

1. 核心概念
  • 注解处理器:Java 编译器插件,在编译阶段扫描和处理注解
  • 工作流程
    graph LR
    A[源代码] --> B[编译器调用APT]
    B --> C[注解处理器扫描]
    C --> D[生成新代码]
    D --> E[编译新代码]
    

2. 实现步骤
2.1 定义自定义注解
import java.lang.annotation.*;

@Retention(RetentionPolicy.SOURCE) // 仅保留在源码阶段
@Target(ElementType.TYPE)          // 作用于类/接口
public @interface Builder {
    String prefix() default "build"; // 带默认值的元素
}

2.2 创建注解处理器
import javax.annotation.processing.*;
import javax.lang.model.element.TypeElement;
import java.util.Set;

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

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

2.3 注册处理器(META-INF/services)

创建文件:resources/META-INF/services/javax.annotation.processing.Processor 内容:

com.example.BuilderProcessor

3. 代码生成实战(使用JavaPoet)
// 在process方法内添加:
@Override
public boolean process(Set<? extends TypeElement> annotations, 
                       RoundEnvironment roundEnv) {
    for (Element element : roundEnv.getElementsAnnotatedWith(Builder.class)) {
        Builder builder = element.getAnnotation(Builder.class);
        String className = element.getSimpleName() + "Builder";
        
        // 使用JavaPoet生成构建器类
        TypeSpec builderClass = TypeSpec.classBuilder(className)
            .addModifiers(Modifier.PUBLIC, Modifier.FINAL)
            .addMethod(generateBuildMethod(element))
            .build();
        
        // 写入源文件
        JavaFile.builder(getPackage(element), builderClass)
                .build()
                .writeTo(processingEnv.getFiler());
    }
    return true;
}

4. 编译配置(Maven)
<dependencies>
    <dependency>
        <groupId>com.squareup</groupId>
        <artifactId>javapoet</artifactId>
        <version>1.13.0</version>
    </dependency>
    <dependency>
        <groupId>com.google.auto.service</groupId>
        <artifactId>auto-service</artifactId>
        <version>1.0-rc7</version>
    </dependency>
</dependencies>

<build>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-compiler-plugin</artifactId>
            <version>3.8.1</version>
            <configuration>
                <annotationProcessorPaths>
                    <path>
                        <groupId>com.google.auto.service</groupId>
                        <artifactId>auto-service</artifactId>
                        <version>1.0-rc7</version>
                    </path>
                </annotationProcessorPaths>
            </configuration>
        </plugin>
    </plugins>
</build>

5. 使用示例
@Builder(prefix = "create")
public class User {
    private String name;
    private int age;
}

// 编译后自动生成:
public final class UserBuilder {
    public User create() {
        return new User(); // 实际生成带参数的构建方法
    }
}

6. 调试技巧
  1. 启用编译日志:
    mvn clean compile -X
    

  2. 处理循环: $$ \text{轮次} = \begin{cases} \text{初始轮} & \text{处理原始注解} \ \text{后续轮} & \text{处理生成的代码} \end{cases} $$
  3. 错误处理:使用processingEnv.getMessager()输出错误信息

最佳实践:优先使用注解处理框架(如Google Auto),避免手动文件注册。生成代码时注意避免符号冲突,建议使用$作为生成类分隔符(如User$Builder

Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐