Java自定义注解需三步:声明@Target和@Retention元注解、用接口语法定义带默认值的属性、通过反射或框架解析执行;属性类型仅限String、基本类型、Class、枚举、注解及其一维数组。

Java 自定义注解不是写个标签就完事,关键在三步:声明元注解定范围和生命周期、用接口语法定义属性、再通过反射或框架读取执行逻辑。属性必须有明确类型和默认值规则,否则编译报错。
必须加的两个元注解
每个自定义注解都得带 @Target 和 @Retention,缺一不可。
-
@Target 指明能标注在哪:比如只允许方法上,写
@Target(ElementType.METHOD);支持多个位置就用数组,如@Target({ElementType.TYPE, ElementType.METHOD}) -
@Retention 决定能活多久:运行时要读取(比如 AOP 日志、权限校验),必须选
RetentionPolicy.RUNTIME;仅编译检查可用SOURCE
属性怎么声明和设默认值
注解里的“属性”其实是接口中的抽象方法,类型受限,但覆盖常见需求。
- 允许的类型:String、基本类型(int/boolean等)、Class<?>、枚举、其他注解,以及这些类型的**一维数组**
- 每个属性后必须跟
(),有默认值就加default 值;没默认值,使用时必须显式赋值 - 如果唯一要填的属性叫
value,调用时可省略名字,直接写@MyLog("操作说明") - 数组属性单元素可不写花括号,
roles = "ADMIN"等价于roles = {"ADMIN"}
一个带多属性的日志注解示例
比如标记方法是否记录入参、操作类型和日志级别:
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
立即学习“Java免费学习笔记(深入)”;
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Log {
String value() default "";
LogLevel level() default LogLevel.INFO;
boolean recordParams() default true;
String[] excludeFields() default {};
}
-
@Log("创建订单")—— 全用默认值 -
@Log(value = "删除缓存", recordParams = false)—— 显式覆盖部分 -
@Log(value = "权限校验", excludeFields = {"password", "token"})—— 数组赋值
注解本身不干活,得靠后续解析
定义完只是存了元数据,真正起作用要靠处理机制:
- 在 Spring 中,常配合
@Aspect切面,在@Around或@Before中用method.getAnnotation(Log.class)取配置 - 纯 Java 项目可用反射:遍历 Method 对象,调用
isAnnotationPresent()或getAnnotation()获取实例 - 注意:若属性类型是自定义类(如
MyConfig),会编译失败——只允许基本类型、String、Class、枚举、注解及它们的数组

















