Java注解本身是元数据,不参与运行;编译期通过@Retention(SOURCE)和AnnotationProcessor处理AST生成代码,运行期通过@Retention(RUNTIME)配合反射读取,但需注意生命周期、类加载器及语义约定。
Java 注解本身不参与运行,它们只是元数据;真正参与运行的是你写的 AnnotationProcessor(编译期)或通过反射读取注解的代码(运行期)。
注解怎么在编译期起作用:@Retention(RetentionPolicy.SOURCE) 和 AnnotationProcessor
这类注解只保留在源码阶段,比如 @Override、@SuppressWarnings。自定义时需配合 javax.annotation.processing.AbstractProcessor 实现编译期逻辑:
- 必须声明
@SupportedAnnotationTypes指定处理哪些注解 - 不能在 processor 里用反射读取被注解的类——此时字节码还没生成,只能用
Element和TypeMirrorAPI 分析 AST - 生成新文件要用
Filer.createSourceFile(),不能直接写磁盘 - Maven 中需用
maven-compiler-plugin配置annotationProcessors,否则 processor 不会被触发
注解怎么在运行期起作用:@Retention(RetentionPolicy.RUNTIME)
只有标了 @Retention(RetentionPolicy.RUNTIME) 的注解才能被反射读到。关键点在于:
-
Class.getAnnotation(Class)、Method.getAnnotation(Class)等方法返回的是代理对象,不是原始注解实例 - 注解接口的方法不能有参数、不能抛异常、不能有默认值以外的实现(即所有方法都必须有 default 值)
- 反射读取性能较低,频繁调用建议缓存结果,比如 Spring 就把
@RequestMapping解析结果存在HandlerMapping中 - 注意类加载器隔离问题:如果注解类由不同 ClassLoader 加载(如 OSGi 或某些容器),
isAnnotationPresent()可能返回 false,即使源码写了
常见踩坑:为什么我的注解“没生效”?
多数失效不是注解写错了,而是生命周期或使用方式不匹配: