Java注解能力提升关键在于理解处理时机与方式,并分四步实践:一、明确@Retention(SOURCE/CLASS/RUNTIME)和@Target作用范围;二、编写运行时反射处理器(如AOP切面);三、进阶用APT编译期生成代码;四、规避魔法代码,规范设计。

Java 注解能力提升,关键不在背语法,而在理解“谁在什么时候、用什么方式处理注解”,以及如何让注解真正驱动逻辑。下面从实战角度分四块讲清楚。
一、搞清注解的生命周期和作用目标
不区分 @Retention 和 @Target,写再多注解也容易失效。
-
@Retention(RetentionPolicy.SOURCE):只在源码阶段存在,如
@Override,编译后就没了,运行时拿不到 - @Retention(RetentionPolicy.CLASS):默认值,编译进 class 文件但不加载进 JVM,字节码工具(如 ASM)能读,反射读不到
- @Retention(RetentionPolicy.RUNTIME):运行时可用,反射才能获取——绝大多数自定义注解必须设为这个
-
@Target 要写全:比如想用在方法参数上,就得加
ElementType.PARAMETER;想支持构造器,别漏掉ElementType.CONSTRUCTOR
二、动手写一个可工作的自定义注解 + 处理器
光定义注解没用,得有“人”去执行它。推荐从运行时反射处理器起步,再过渡到编译期(APT)。
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
- 定义注解:@interface LogExecutionTime { String value() default ""; }
- 用在方法上:@LogExecutionTime("user-service") public void loadUser(int id) { ... }
- 写个通用 AOP 切面(Spring 环境)或手动反射调用(非 Spring):
在方法执行前后取时间差,打印耗时,value() 值可作为日志前缀或指标标签 - 注意:若不用 Spring,需自己遍历类中所有带该注解的方法,并用
Method.invoke()包装逻辑——这是理解注解驱动的关键一步
三、进阶:用 APT 在编译期生成代码
运行时反射有性能开销,且无法做编译检查。APT(Annotation Processing Tool)让你在 javac 阶段就生成 Java 源文件。
立即学习“Java免费学习笔记(深入)”;
- 新建注解,加
@Retention(RetentionPolicy.SOURCE) - 写一个
AbstractProcessor子类,重写process()方法,用RoundEnvironment扫描被注解的元素 - 用
Filer写出新类,用Elements和Types安全获取类型信息(避免字符串硬编码) - 常见场景:替代 ButterKnife 的
@BindView,或为接口自动生成 Builder 类
四、避坑与设计习惯
很多注解用着用着就变成“魔法代码”,根源常在设计失当。
- 不要把复杂逻辑塞进注解属性里——注解属性只能是常量表达式(基本类型、String、Class、枚举、其他注解、以上类型的数组)
- 避免“注解套注解”过深,三层以上就难维护;必要时改用配置类 + 注解标记主入口
- 同一个业务尽量统一注解风格:比如都用
String[] value()支持多值,或都提供order()控制执行顺序 - 对外发布的注解库,务必提供清晰的文档说明“谁负责处理它”“是否需要额外依赖”“是否线程安全”

















