Java注解处理器通过RoundEnvironment获取带注解的ExecutableElement,提取方法名、参数、所在类及注解属性值,再用Javapoet生成代理代码,注意包名一致性、类名避重、泛型擦除限制及注解保留策略配置。

在 Java 注解处理器(Annotation Processor)中,要为带有特定注解的方法生成辅助代码(如代理方法、日志拦截、参数校验等),核心是:通过 RoundEnvironment 获取被注解的方法元素(ExecutableElement),再利用 Filer 和 Javapoet(或原生 JavaFileObject)生成新的 .java 源文件。
获取带注解的方法元素
在 process() 方法中,用 roundEnv.getElementsAnnotatedWith(YourMethodAnnotation.class) 获取所有被目标注解标记的元素。需过滤出 ExecutableElement 类型(即方法),避免误处理类、字段等:
- 用
element instanceof ExecutableElement判定是否为方法 - 调用
((ExecutableElement) element).getParameters()获取参数列表 - 用
element.getEnclosingElement()获取所在类(返回TypeElement) - 通过
element.getSimpleName().toString()获取方法名
提取注解属性值
若自定义注解含属性(如 @AutoLog(level = "DEBUG")),需从 ExecutableElement 中读取实际值:
- 调用
element.getAnnotationMirrors()获取所有注解镜像 - 遍历找到目标注解镜像后,用
annotationMirror.getElementValues()获取键值对 - 对每个
AnnotationValue,用value.getValue()提取运行时值(注意:字面量、枚举、Class 类型需特殊处理,如ClassName.get(...)转换)
生成辅助类或方法
推荐使用 Javapoet 构建源码,比手拼字符串更安全、可维护:
立即学习“Java免费学习笔记(深入)”;
- 用
TypeName.get(method.getReturnType())获取返回类型 - 用
ParameterSpec和ParameterizedTypeName构建参数声明 - 用
MethodSpec.builder("proxy" + methodName)创建新方法,添加.addStatement("return $N($L)", originalMethodName, joinParams) - 用
JavaFile.builder(packageName, typeSpec).build().writeTo(filer)输出到磁盘
注意:生成的类名不能与已有类冲突,建议加统一后缀(如 $$Proxy);包名必须与原类一致或为子包,否则无法访问默认访问权限成员。
处理泛型和类型擦除限制
注解处理器运行在编译期,仅能看到源码级信息,无法获取运行时泛型实参(如 List<String> 在 ExecutableElement 中表现为 List<?>):
- 用
Types工具类(如types.erasure(type))做类型归一化 - 若需精确泛型信息,可结合
DeclaredType和getTypeArguments()尝试还原(但嵌套泛型支持有限) - 避免依赖
instanceof或反射——注解处理器中这些不可用
不复杂但容易忽略:确保注解声明时设置 @Retention(RetentionPolicy.SOURCE),并在 processor 的 getSupportedAnnotationTypes() 中正确注册全限定名;同时在 resources/META-INF/services/javax.annotation.processing.Processor 中声明处理器类名。


















