@inherited注解在多层纯extends继承链中可跨层级传递,前提是每层父类均声明同一@inherited修饰的type级runtime注解且子类未重复标注;接口、方法、字段及spring元注解均不生效。

多层继承中@Inherited的实际查找路径
@Inherited 不限制继承层级,只要继承链是纯 extends 关系(A → B → C → D),且中间每个类都未显式声明同类型注解,那么最底层子类调用 getAnnotation() 就能获取到顶层父类上被 @Inherited 修饰的类级注解。JVM 的反射查找会沿着 getSuperclass() 链一直向上,直到找到该注解或抵达 Object.class。
关键前提:每层都必须满足三个硬性条件
整个传递链要生效,不是“某一层满足就行”,而是:
- 每个被标注的父类(如 A、B)本身必须使用了同一个被 @Inherited 修饰的注解;
- 该注解自身必须同时声明:
• @Target(ElementType.TYPE)
• @Retention(RetentionPolicy.RUNTIME)
• @Inherited
- 子类不能在自身类声明处重复标注同一注解(否则会覆盖继承来的值,只返回子类自己的)。
常见误解:接口、组合、重写方法不参与此机制
以下情况无论多少层继承都完全无效:
- 接口上定义了带 @Inherited 的注解,实现类无法继承;
- 父类通过 Spring 注解(如 @Service)间接获得元数据,子类查不到;
- 方法或字段上加了 @Inherited 元注解——语法合法但无任何效果;
- 子类重写了父类方法,即使父类方法上有注解,子类 getMethod().getAnnotation() 仍返回 null。
如何验证是否真正传递成功
建议用两段代码交叉验证:
- clazz.getAnnotation(MyConfig.class):返回非 null 表示继承链查找成功;
- clazz.getDeclaredAnnotation(MyConfig.class):应始终为 null(除非子类自己写了);
- 若需支持“跨多层 + 接口 + 默认方法兜底”,应手动封装向上遍历逻辑,不能依赖 @Inherited 自动完成。











