Java注解不支持语法继承,组合功能需靠元注解(如@Target、@Retention)声明组合注解,或借助@Inherited实现类级注解传递,或运行时扫描+手动触发逻辑,或编译期APT生成辅助代码。

Java 中注解本身不支持真正的“继承”——你不能让一个注解像类那样 extends 另一个注解,也不能通过声明方式自动把 @Valid、@Convert 等行为“传递”到被标注的字段上。所谓“组合多个注解的功能”,本质是靠元注解声明 + 运行时/编译期协同机制来实现语义聚合,而不是语法继承。
用元注解构建组合注解(最常用、最标准)
这是 Spring 等主流框架广泛采用的方式:把多个已有注解直接写在自定义注解定义上,并用 @Target、@Retention 等元注解约束其作用范围和生命周期。
- @Target 和 @Retention 是必须的,否则自定义注解无法生效;
- 把 @RestController、@RequestMapping、@Validated 等注解直接加在自定义注解上,它们会在该注解被使用时“一并激活”;
- 配合 @AliasFor 可桥接属性,比如让 @MyApi(path = "/user") 等效于 @RequestMapping(value = "/user");
- 注意:这种组合只对 Spring 容器识别的注解有效(如 MVC、Validation 模块),不是所有注解都能被自动“展开”。
靠 @Inherited 实现类层级的注解传递(有限场景)
@Inherited 是唯一一个带“继承”语义的元注解,但它只对类(ElementType.TYPE)生效,且仅限子类继承父类时向上传播,不适用于方法、字段或接口。
- 如果父类标记了 @MyComponent,且该注解加了 @Inherited,则子类 class B extends A 会自动“拥有”该注解;
- 但字段上的 @EmailField 加了 @Inherited 是无效的,因为字段不可被继承;
- 它不解决“组合功能”的问题,只是简化了类级别的注解复用。
运行时扫描 + 手动触发配套逻辑(灵活但需自行维护)
当组合需求超出元注解能力(例如需要动态注入带参数的 @Convert(converter = X.class)),就得在运行时主动识别并补全行为:
- Spring 环境下,可用 @Configuration + @Bean 扫描含 @EmailAddressField 的字段,自动注册对应的 Validator、Converter、JsonSerializer;
- 非 Spring 环境,可通过反射遍历类中所有字段,检查是否含某注解,再手动调用校验逻辑或转换器;
- 这种方式不依赖注解“自动生效”,但控制力强、适配性高,适合复杂业务规则。
编译期注解处理器(APT)生成辅助代码(高级可控方案)
如果你需要在编译阶段就生成校验逻辑、DTO 映射、JSON 序列化配置等,可写 Annotation Processor:
- 处理器扫描 @EmailAddressField,生成对应 XxxValidator 类或 Jackson Module 配置代码;
- 不能修改原字段的注解集合(Element.getAnnotationMirrors() 是只读的),但能生成配套类、资源或配置;
- Lombok、MapStruct 都走这条路,适合对构建流程有掌控权的中大型项目。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











