source注解无法用于运行时代码检查,因其仅保留在源码阶段,编译后即从class文件中丢弃,反射和字节码工具均不可见;正确做法是配合注解处理器在编译期使用。

RetentionPolicy.SOURCE 无法用于运行时代码检查,因为它只保留在源码阶段,编译后即被丢弃,无法在编译后或运行时读取。
为什么 SOURCE 注解不能做代码检查
Java 注解的保留策略决定了它在哪个阶段可用:
- SOURCE:仅在源码中存在,javac 编译时可用,但不会写入 .class 文件,编译后彻底消失
- CLASS:写入字节码,但 JVM 加载时不加载,反射不可见
- RUNTIME:写入字节码且 JVM 加载后可通过反射获取——这是运行时检查(如 Spring、JUnit)依赖的基础
因此,任何需要在编译后分析代码的工具(如自定义注解处理器、静态检查、字节码扫描、运行时 AOP 或校验逻辑),都不能依赖 SOURCE 级注解。
想做代码检查?该用 PROCESSOR + CLASS 或 RUNTIME
真正可行的路径是使用 注解处理器(Annotation Processor),它在编译期(javac 执行时)工作,能读取 SOURCE 级注解并生成提示、文件或报错:
- 注解声明需加
@Retention(RetentionPolicy.SOURCE)和@Target - 编写
javax.annotation.processing.Processor子类,在process()中遍历 AST(通过RoundEnvironment获取元素) - 用
Messager输出警告/错误(如messager.printMessage(Diagnostic.Kind.ERROR, "...", element)) - 注册处理器:在
META-INF/services/javax.annotation.processing.Processor中写入全限定类名
例如:定义 @DeprecatedApi(SOURCE 级),注解处理器扫描到该注解出现在非废弃方法上调用时,直接报编译错误。
常见误解与替代方案
有人试图用 SOURCE 注解配合反射或字节码库(如 ASM)做检查——这注定失败,因为注解信息已不存在于 class 文件中。
- 若需构建期检查(如 Maven 编译时),用注解处理器(Processor)+ SOURCE 是正解
- 若需运行时校验(如参数合法性),必须用 RUNTIME,并配合反射或代理
- 若需 IDE 实时提示(如 IntelliJ 警告),可结合注解处理器 + IDE 的 Annotation Tooling 支持,或使用 Lombok-style 插件机制
小结
RetentionPolicy.SOURCE 的唯一正确定位是“编译期元数据”,服务于注解处理器。把它当作运行时检查的入口,会因信息丢失而失效。工具链设计要匹配生命周期:SOURCE → Processor;RUNTIME → Reflection/AOP;CLASS → 字节码分析(如 Checkstyle 集成版、ArchUnit)。选错保留策略,整个检查逻辑就失去基础。








