注解在JVM类加载时仅按@Retention策略存入字节码或内存,不执行逻辑;必须通过反射API(如getAnnotation、isAnnotationPresent)显式读取才能激活其功能。

注解在 JVM 加载类时不会被自动解析执行,只是按保留策略(@Retention)决定是否写入字节码、是否保留在运行时内存中;真正读取和使用注解,必须由程序显式调用反射 API(如 getAnnotation()、isAnnotationPresent() 等)。
注解在类加载阶段只做“加载”,不“解析逻辑”
JVM 在类加载的“连接”阶段(特别是解析阶段),会从字节码的 RuntimeVisibleAnnotations 或 RuntimeInvisibleAnnotations 属性表中读取注解的类型和属性值,并将其加载进方法区(元空间),生成对应的 Annotation 对象实例——但这只是把注解作为元数据存好,不触发任何业务逻辑。
换句话说:JVM 不知道这个注解有什么用,也不关心它该做什么。它只负责“搬进来”,不负责“用起来”。
只有反射调用才真正“激活”注解
要让注解产生实际效果(比如打印日志、校验参数、注入 Bean),必须在代码中主动使用反射获取注解信息:
当用户要求为 Java 代码添加注释、修改注释、审查注释、整理注释格式,或要求按照代码注释规范处理 Java 文件时,使用本技能。本技能用于统一生成和维护 Java 类注释模板、按 Git 对比 release 判断版本号、补充每行代码上方中文块注释、调整注释空行规则,并保持 Java 文件 UTF-8 无 BOM 编码。典型触发场景包括:补充类注释、更新 @version、检查 @author 来源、整理行尾注释、把注释放到代码上一行、检查注释是否符合规范、构建前检查 Java 注释风格。
-
clazz.getAnnotation(MyAnnotation.class)获取类上的注解 -
method.isAnnotationPresent(LogExecution.class)判断方法是否标注了某注解 -
field.getAnnotation(Inject.class)拿到字段上的依赖注入标记
框架(如 Spring、JUnit)内部就是靠大量这类反射调用,配合注解的 @Retention(RUNTIME) 策略,实现在运行时动态识别和响应注解。
注解是否可用,取决于 @Retention 设置
不是所有注解都能被反射读到:
-
@Retention(RetentionPolicy.SOURCE):仅保留在源码,编译后就丢弃(如@Override),反射完全不可见 -
@Retention(RetentionPolicy.CLASS):写入 class 文件但运行时 JVM 不加载到内存,反射也拿不到 -
@Retention(RetentionPolicy.RUNTIME):唯一支持反射读取的策略,必须显式声明才能用于运行时处理
常见误区澄清
有人以为加了 @Transactional 方法就自动开启事务——其实不是 JVM 或编译器做的,而是 Spring AOP 在启动时扫描所有 @Bean 方法,用反射检查 @Transactional,再动态织入代理逻辑。没有反射调用,注解就是一段静态描述,什么也不会发生。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










