Java原生@Deprecated不支持自定义属性和反射读取提示文字,需自定义@DeprecatedSince注解(含value/version字段)、通过反射扫描提取说明,并兼容原生@Deprecated以增强审计能力。

Java 原生的 @Deprecated 是一个内置注解(`java.lang.Deprecated`),它**不支持自定义属性**,也不能被反射直接“读取提示文字”。你无法通过反射获取类似 @Deprecated("请改用 newMethod()") 这样的字符串值——因为标准 @Deprecated 的定义中根本没有 value 字段。
所以,要实现“动态代码审计”中识别带说明的弃用方法,你需要的是:一个自定义的、可携带描述信息的弃用注解,再配合反射读取它。以下是具体做法:
1. 定义可携带说明的自定义弃用注解
创建一个保留策略为 RUNTIME 的注解,允许通过反射访问,并添加 value() 或 reason() 字段存储提示文本:
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface DeprecatedSince {
String value() default "该方法已弃用,请检查替代方案";
String version() default "";
}
这样就能在方法上使用:
立即学习“Java免费学习笔记(深入)”;
分析 Java Spring Boot 后端 Controller 代码,自动生成 Markdown 格式的接口文档。当用户说“生成 Java 接口文档”、“生成 API 文档”、“从 Spring 代码生成文档”时触发。
@DeprecatedSince("请改用 calculateV2(),精度更高")
public double calculate() { ... }
2. 用反射扫描类中的废弃方法并提取提示
遍历目标类的所有 Method,检查是否标注了你的自定义注解,并读取其字段:
- 调用
method.getAnnotation(DeprecatedSince.class) - 若返回非 null,说明该方法被标记为弃用
- 调用
annotation.value()或annotation.reason()获取提示文本 - 可结合
method.getDeclaringClass()和method.getName()构建完整签名用于审计报告
3. 集成到审计流程(例如启动时扫描或测试阶段)
常见实用方式包括:
- 在 Spring Boot 启动时,用
ClassPathScanningCandidateComponentProvider扫描特定包下所有@Component类,再反射检查其 public 方法 - 编写 JUnit 测试,对指定模块的 API 类批量校验:发现带
@DeprecatedSince但未加@Test或未被日志/监控覆盖的方法,自动失败 - 与 IDE 插件或 SonarQube 自定义规则联动:将注解信息导出为 JSON 报告供静态分析消费
4. 补充建议:兼容原生 @Deprecated 并增强语义
如果你仍需兼容 JDK 自带的 @Deprecated(比如第三方库方法),可以同时检查:
-
method.isAnnotationPresent(Deprecated.class)→ 表示基础弃用标记 - 再叠加检查你的
@DeprecatedSince→ 提供可读原因 - 两者共存时,优先采用自定义注解的
value(),作为审计报告中的“弃用说明”
这样既不破坏现有约定,又提升了可维护性与自动化审计能力。

















