1.@Target(ElementType.METHOD)
作用:规定注解的使用位置。
含义:这行代码限制了你的自定义注解只能标记在方法(Method)上。
效果:如果你尝试把这个注解加在类(Class)、字段(Field)或者包(Package)上,编译器会直接报错。
常见的 ElementType 类型:
METHOD:只能用于方法。TYPE:用于类、接口、枚举。FIELD:用于成员变量。PARAMETER:用于方法参数。
举例:就像是给一张贴纸印上了“仅限贴在门把手上”,如果你贴在窗户上就是违规的。
2.@Retention(RetentionPolicy.RUNTIME)
作用:规定注解的生命周期(存活时间)。
含义:这行代码表示你的注解会一直保留到程序运行期间 (Runtime)。
核心用途:这是最关键的一点。只有设置为
RUNTIME,程序才能在运行时通过反射 (Reflection)机制读取到这个注解。如果不加这一行(或者设为其他值),你的代码跑起来的时候,这个注解就已经“消失”了,程序无法检测到它。
RetentionPolicy 的三个阶段对比:
| 策略 (Policy) | 存活范围 | 说明 | 典型应用 |
SOURCE | 源码阶段 | 编译成.class文件后就被丢弃了。 | 如@Override,@SuppressWarnings |
CLASS(默认) | 字节码阶段 | 存在于.class文件中,但 JVM 加载运行时会忽略它。反射拿不到。 | Lombok, 编译时处理工具 |
RUNTIME | 运行阶段 | 一直存在于 JVM 中,可以通过反射动态获取。 | Spring AOP, 自定义拦截器 |
举例:就像你写了一张便利贴:
SOURCE:看完就扔进垃圾桶。
CLASS:夹在书里存进了档案室,但平时工作时不拿出来看。
RUNTIME:贴在电脑屏幕边框上,随时干活随时看(程序运行时随时读取)。
3. 实际应用场景:AOP 与 拦截器
当你把这两个注解结合在一起时,通常是为了实现AOP(面向切面编程)或拦截器功能。
代码示例:一个用于记录日志的自定义注解
import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; // 1. 定义注解:只能用在方法上,且运行时可通过反射读取 @Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) public @interface MyLog { String value() default ""; }如何使用:
public class UserService { // 2. 正确使用:标记在方法上 @MyLog("记录用户登录操作") public void login() { System.out.println("用户正在登录..."); } // 错误使用:如果把 @MyLog 加在字段上,编译器会报错,因为 @Target 限制了只能是 METHOD // @MyLog // private String name; }程序运行时(Spring AOP 或 反射)的逻辑:
程序运行到
login()方法。通过反射检查
login()方法头上有没有@MyLog注解。因为是
RUNTIME,所以能扫描到。读取注解里的内容("记录用户登录操作"),然后自动执行写日志的代码。
4.总结
@Target(ElementType.METHOD):划定界限,告诉编译器这个标签只能贴在方法上。@Retention(RetentionPolicy.RUNTIME):延长寿命,告诉 JVM程序运行时不要丢掉这个标签,因为我们的逻辑代码(如拦截器)需要读取它。