Java自定义注解需经声明、使用、反射三步才生效:先用@Target和@Retention(RUNTIME)等元注解定义作用范围与生命周期,再设计属性并标注使用,最后通过isAnnotationPresent()和getAnnotation()等反射API读取处理。

Java自定义注解不是“写完就能用”,必须配合元注解约束行为、明确作用范围,并通过反射在运行时提取信息才能真正生效。整个流程分三步:声明注解、标注使用、反射读取。
一、用元注解定义注解本身
自定义注解本质是一个带特殊语义的接口,需用 @interface 声明,并至少配置两个核心元注解:
-
@Target:指定能加在哪儿,比如
ElementType.METHOD(方法)、ElementType.TYPE(类)、ElementType.FIELD(字段)等;可传数组,如@Target({METHOD, TYPE}) -
@Retention(RetentionPolicy.RUNTIME):这是反射读取的前提——只有设为
RUNTIME,注解才会保留在字节码中并被 JVM 加载,反射才能拿到 - 可选补充:@Documented(生成 Javadoc 时包含该注解)、@Inherited(仅对类注解有效,子类自动继承)
二、设计注解属性并使用
注解属性写法类似接口方法,不带参数、有返回值,支持默认值和常用类型:
- 基本类型(int、boolean)、String、Class、枚举、其他注解类型,以及它们的一维数组
- 用 default 设默认值,例如
String value() default ""; - 若只有一个属性且名为
value(),使用时可省略键名,如@MyLog("debug") - 数组属性单元素可省略大括号,如
roles = "admin"等价于roles = {"admin"}
三、用反射读取并处理注解
注解本身不执行逻辑,真正起作用的是你写的反射代码。关键 API 就两个:
立即学习“Java免费学习笔记(深入)”;
-
xxx.isAnnotationPresent(YourAnnotation.class):快速判断是否存在该注解 -
xxx.getAnnotation(YourAnnotation.class):获取注解实例,再调用其属性方法取值 - xxx 可以是
Class对象(查类注解)、Method对象(查方法注解)、Field对象(查字段注解)等 - 注意:必须确保注解类已加载,且保留策略为 RUNTIME,否则返回 null 或 false
四、典型使用场景示例
实际开发中,这套流程支撑着很多框架能力:
- 日志埋点:定义
@Log(level="INFO"),反射读取后自动记录方法执行日志 - 权限校验:定义
@RequiresRole("ADMIN"),拦截器里反射检查当前用户角色 - 数据校验:定义
@NotNull(message="用户名不能为空"),验证逻辑根据注解属性抛出提示 - 路由映射:定义
@RequestMapping("/user/list"),Dispatcher 根据反射结果分发请求


















