注解处理器在编译期通过element和typemirror提取java变量元数据,不操作运行时值;需过滤field元素、调用variableelement方法获取名称类型等,并用filer生成json或java文件。

Java 变量本身不能直接“在注解处理器中生成”,但变量的元数据(如名称、类型、修饰符、所属类、是否被特定注解标记等)可以在注解处理器中被提取、分析,并用于生成新的元数据文件(如 spring-configuration-metadata.json)或辅助代码(如 Builder 类、DTO 映射类等)。
关键在于:注解处理器运行在编译期,它不操作运行时变量值,而是通过 Java 编译器提供的 javax.annotation.processing 和 com.sun.source.tree 等 API,扫描源码中的元素(包括字段/变量),读取其结构信息和关联注解,再据此生成新文件或类。
注解处理器如何获取并处理 Java 变量的元数据
你需要在处理器中:
- 使用
RoundEnvironment获取所有被目标注解标记的元素; - 过滤出
ElementKind.FIELD类型的元素(即类中的成员变量); - 调用
VariableElement接口方法提取变量信息; - 结合
Types、Elements工具类解析类型、包名、默认值等; - 最终写入 JSON 文件或生成
.java源文件。
例如,处理一个带 @ConfigurationProperties 的配置类:
@ConfigurationProperties(prefix = "app")
public class AppProperties {
private String name;
private int version;
}
注解处理器会识别 AppProperties 类,遍历其所有 FIELD 元素,提取:
- 字段名:
name,version - 类型:
String,int - 所属类:
AppProperties - 是否有
@NotNull、@DefaultValue等扩展注解
然后生成元数据片段:
{
"name": "app.name",
"type": "java.lang.String",
"description": "",
"sourceType": "com.example.AppProperties"
}
实现步骤简明清单
声明支持的注解
在process()方法开头,用getSupportedAnnotationTypes()声明要监听的注解(如"org.springframework.boot.context.properties.ConfigurationProperties")。-
遍历被注解的类型元素
for (Element element : roundEnv.getElementsAnnotatedWith(ConfigurationProperties.class)) { if (element.getKind() == ElementKind.CLASS) { TypeElement typeElement = (TypeElement) element; // 遍历该类所有字段 for (Element enclosed : typeElement.getEnclosedElements()) { if (enclosed.getKind() == ElementKind.FIELD) { VariableElement field = (VariableElement) enclosed; String fieldName = field.getSimpleName().toString(); TypeMirror fieldType = field.asType(); // 获取类型全限定名:types.erasure(fieldType).toString() // 获取是否为 final / static:field.getModifiers() } } } } -
使用工具类增强解析能力
-
Types:解析泛型、原始类型、数组等 -
Elements:获取包名、类名、Javadoc 注释 -
Messager:输出编译期提示或错误
-
-
生成元数据文件(如 JSON)
使用Filer创建资源文件(非.java):FileObject resource = filer.createResource( StandardLocation.CLASS_OUTPUT, "", "META-INF/spring-configuration-metadata.json" ); try (Writer writer = resource.openWriter()) { writer.write(jsonContent); // 手动拼或用 Jackson/Gson 序列化 }
注意事项
- 注解必须声明为
@Retention(RetentionPolicy.SOURCE)或CLASS,才能被注解处理器读到(RUNTIME注解也可,但非必需); - 不要依赖反射(
Class>),因为源码尚未编译成 class,只能用Element和TypeMirror; - 字段默认值(如
private String env = "dev";)无法直接从VariableElement获取,需借助TreePath+JavacTrees(较复杂,通常只处理@DefaultValue("xxx")这类显式注解); - Spring Boot 的
spring-boot-configuration-processor就是典型实现,它扫描@ConfigurationProperties并生成spring-configuration-metadata.json,供 IDE 提示和配置校验使用。
不复杂但容易忽略。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











