@repeatable 为注解复用提供规范框架,由编译器转换、容器契约和反射增强三部分协同实现;业务注解需标注@repeatable并满足元注解约束,容器注解须严格符合三项硬性条件,运行时必须使用getannotationsbytype获取实例。

Java 8 引入 @Repeatable,不是为了绕过限制,而是构建一套“源码简洁、字节码合规、运行时可控”的注解复用框架。它由编译器转换、容器契约和反射增强三部分协同工作,缺一不可。
业务注解必须显式声明可重复性
你的自定义注解(如 @Role)需直接标注 @Repeatable(Roles.class),并满足基础元注解约束:
-
@Retention(RetentionPolicy.RUNTIME)—— 否则反射无法读取 -
@Target明确指定适用位置(如ElementType.METHOD),且后续容器必须完全一致 - 所有属性建议提供默认值,避免使用时强制赋值
容器注解是强制配套,不是可选包装
容器(如 @Roles)不是命名习惯,而是编译器识别重复语义的唯一桥梁,必须严格满足三项硬性条件:
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
- 必须是
@interface类型,不能是普通类或接口 - 仅含一个名为
value()的方法,返回类型为对应业务注解的数组(如Role[] value();) -
@Retention和@Target必须与业务注解逐字相同,少一个ElementType就会编译失败
运行时必须用专用反射方法获取全部实例
字节码中只保留容器注解,原始重复注解不会单独出现。因此传统反射方式失效:
-
getAnnotation(Role.class)总是返回null或未定义行为,不可依赖 -
getAnnotationsByType(Role.class)是唯一推荐方式——自动识别容器、展开value()数组、合并继承链上的同类注解 -
getDeclaredAnnotationsByType(Role.class)适用于仅需当前声明位置的场景,不向上查找父类或接口
编译期转换与字节码真相
写 @Role("A") @Role("B") 看似直觉,实则编译器做了关键转换:
- 将多个
@Role合并为单个@Roles({@Role("A"), @Role("B")}) - 最终 class 文件的
RuntimeVisibleAnnotations属性中,只存在@Roles条目 - 用
javap -v反编译可验证:@Role不会作为独立注解出现在字节码里
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










