java自定义注解的核心在于精准组合四个元注解:@target和@retention为运行生效底线,必须同时存在且搭配合理;@documented提升文档可维护性;@inherited和@repeatable按需启用;属性设计应少而稳,优先默认值、禁用复杂类型、命名清晰。

Java自定义注解不是靠堆砌元注解来“高级”,而是靠精准组合实现明确意图。真正可靠的注解,核心在于四个元注解各司其职、不缺不滥,再配上安全简洁的属性设计。
@Target 和 @Retention 是运行生效的底线
这两个必须同时出现,且搭配合理,否则注解在运行时根本不可见、不可用:
- @Target 要精确限定作用位置,比如只用于方法就写 @Target(ElementType.METHOD);支持类和字段就用数组:@Target({ElementType.TYPE, ElementType.FIELD})
- @Retention 必须设为 RetentionPolicy.RUNTIME,这是 AOP、参数校验、动态代理等所有反射读取场景的前提;设成 CLASS 或 SOURCE 就无法在运行时获取
- 二者缺一,注解就形同虚设——前者决定“能标在哪”,后者决定“标了能不能被看见”
@Documented 提升团队协作效率
它不改变程序行为,但直接影响可维护性:
- 加了它,Javadoc 会把注解本身及其参数说明(如 value()、enabled())一起生成进文档
- 尤其当注解带多个配置项时,不加等于隐藏接口契约,新成员得翻源码才能理解怎么用
- 建议默认加上,成本为零,收益明确
@Inherited 和 @Repeatable 按需启用,误用反增风险
它们不是“高级感”的装饰,而是有明确语义边界的特殊能力:
- @Inherited 只对类级注解有效,且仅在直接继承时生效;接口实现、组合、代理、泛型类型均不传递,别指望它自动透传到子模块
- @Repeatable 需要配套定义容器注解(如 @Roles 容纳多个 @Role),适合权限、标签等天然多值场景;单功能注解(如 @Log、@Retry)强行加只会让调用方多写一层包装
- 不确定是否需要?先不加;后期真有明确需求再引入,比修复误用更省力
注解属性设计:少即是多,稳是前提
属性不是功能越多越好,重点在安全、易用、可演进:
- 必填项尽量少,优先提供 default 值,例如 String value() default ""; 或 int order() default 0;
- 只允许基本类型、String、Class、枚举、其他注解,及其一维数组;禁止 List、Map、自定义对象等复杂类型
- 命名讲求清晰无歧义,比如用 skipIfNull() 而非 ignore(),用 logLevel() 而非 level()
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











