注解(Annotation)本质
注解就是给代码打的标签(元数据),编译后确实会被打包进 .class 文件,所以它可以被编译器、工具或运行时库读取。
三类生命周期
-
源码级(SOURCE)
只在写代码时有效,编译完就消失,不会进 class 文件。@Override:让编译器帮你检查是否真的覆写了父类方法,拼写错误直接报错。@SuppressWarnings:告诉编译器「我知道这里有警告,闭嘴就好」。
-
字节码级(CLASS)
会写进 class 文件,但 JVM 加载类时会丢弃,适合给静态分析工具(如 ProGuard)看。 -
运行时级(RUNTIME) ——最常用
从类加载到程序结束一直留在 JVM 里,随时可以用反射读取。
例如@ResponseBody:当 Spring 检测到方法上有这个注解,就自动把返回值转成 JSON/XML 塞进 HTTP 响应体里,不用你手动写response.getWriter().write()。
自定义注解
用 @interface 关键字定义,本质是特殊的接口:
// 只能贴在类、接口、枚举上
@Target(ElementType.TYPE)
public @interface MyController {
String value(); // 注解的参数,使用时写成 @MyController("/user")
}
// 允许贴在方法或字段上
@Target({ElementType.METHOD, ElementType.FIELD})
public @interface MyLog {
String desc() default "默认日志"; // 可设默认值
}
@Target 的作用:限制你自定义的注解能贴在哪儿,防止写错位置。如果不写 @Target,默认可以贴任何位置。
快速记忆
- 要 检查代码错误 →
@Override(源码级) - 要 框架自动处理(如序列化、事务、权限)→ 自定义 RUNTIME 注解 + 反射
- 写注解时 不知道能贴哪 → 加
@Target约束一下