java注解需设为retentionpolicy.runtime才能被反射读取,通过annotatedelement的getannotation()方法获取,返回代理实例并调用其方法;注解在类加载时解析缓存,多次调用性能开销小。

Java 注解本身不执行任何逻辑,它只是元数据;真正让注解“起作用”的,是运行时通过反射去读取并响应这些信息。要让自定义注解能被读取,关键就两点:注解必须设为 RUNTIME 生命周期,且必须用反射 API 主动获取。
注解必须声明为 RetentionPolicy.RUNTIME
这是前提条件。只有设为 RUNTIME 的注解,JVM 才会在类加载后保留在内存中,反射才能访问到。
- @Retention(RetentionPolicy.SOURCE):编译完就丢弃,反射完全看不到(如 @Override)
- @Retention(RetentionPolicy.CLASS):存在 class 文件里,但 JVM 加载时不进运行时内存,反射也读不到
- @Retention(RetentionPolicy.RUNTIME):唯一能让
getAnnotation()返回非 null 的策略
反射读取注解的核心方法是 getAnnotation()
这个方法定义在 AnnotatedElement 接口上,Class、Method、Field 等都实现了它。
- 读取类上的注解:
MyClass.class.getAnnotation(MyAnnotation.class) - 读取方法上的注解:
method.getAnnotation(MyAnnotation.class) - 读取字段上的注解:
field.getAnnotation(MyAnnotation.class) - 返回值是注解接口的代理实例,可直接调用其方法(如
anno.value())
实际读取过程依赖类加载与元数据结构
JVM 在加载类时,会把 RUNTIME 注解从 class 文件的 RuntimeVisibleAnnotations 属性解析出来,并挂载到对应元素(类、方法、字段)的运行时对象上。反射调用 getAnnotation() 时,本质上就是从这个已加载的元数据缓存中查找匹配类型。
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
- 注解不是实时解析的,而是在类加载阶段一次性提取并缓存
- 同一个类多次调用
getAnnotation(),底层通常复用已有对象,性能开销小 - 如果注解没被正确保留或目标元素没被标注,方法直接返回
null,需判空处理
完整流程示例:定义 → 标注 → 读取
先定义一个运行时注解:
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface LogExecution {
String value() default "log";
}
再在方法上使用它:
@LogExecution("user-service")
public void updateUser() { ... }
最后用反射读取:
Method m = clazz.getDeclaredMethod("updateUser");
LogExecution anno = m.getAnnotation(LogExecution.class);
if (anno != null) {
System.out.println(anno.value()); // 输出 "user-service"
}Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










