注解 java.lang.annotation.Inherited 介绍
在 Spring Boot 中大量使用了 @Inherited 注解。我们来了解一下这个注解的用法,注解的源码:
package java.lang.annotation;/**
- Indicates that an annotation type is automatically inherited. If
- an Inherited meta-annotation is present on an annotation type
- declaration, and the user queries the annotation type on a class
- declaration, and the class declaration has no annotation for this type,
- then the class's superclass will automatically be queried for the
- annotation type. This process will be repeated until an annotation for this
- type is found, or the top of the class hierarchy (Object)
- is reached. If no superclass has an annotation for this type, then
- the query will indicate that the class in question has no such annotation.
- <p>Note that this meta-annotation type has no effect if the annotated
- type is used to annotate anything other than a class. Note also
- that this meta-annotation only causes annotations to be inherited
- from superclasses; annotations on implemented interfaces have no
- effect.
- @author Joshua Bloch
- @since 1.5
- @jls 9.6.3.3 @Inherited
*/
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Inherited {
}
注解的作用:
当某个注解类在它的类上定义了 @Inherited 注解,例如 SpringBoot 中的 @SpringBootApplication 注解,@SpringBootApplication 注解类就定义了 @Inherited 注解,看下源码中的红色部分:
@Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Documented @Inherited @SpringBootConfiguration @EnableAutoConfiguration @ComponentScan(excludeFilters = { @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class), @Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class)}) public @interface SpringBootApplication {// ..... 省略
}
那么现在有一个我们自己开发的类使用了这个注解,例如:
@SpringBootApplication
@Service public class Person {}
然后有个类 Employee 继承了 Person
public class Employee extends Person{}
那么现在在判断 Employee 类上有没有 @SpringBootApplication 时,通过代码验证:
@Test public void test1(){Class clazz </span>= Employee.<span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> ; </span><span style="color: rgba(0, 0, 255, 1)">if</span>(clazz.isAnnotationPresent(SpringBootApplication.<span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)">)){ System.out.println(</span>"true"<span style="color: rgba(0, 0, 0, 1)">); } }</span></pre>
上面这个测试用例执行将输出 true,也就是子类中能查找到 @SpringBootApplication ,但同样,你用上述代码查找 Employee 类上是否有 Spring 的 @Service 注解时,会输出 false,至此你应该明白 @Inherited 注解的用意了吧。
经过这样的分析,我们再来读一下 JDK 的文档,就会比较容易理解了,否则会觉的有些绕,下面列出 @interface 注解的中文文档:
指示注释类型被自动继承。如果在注释类型声明中存在 Inherited 元注释,并且用户在某一类声明中查询该注释类型,同时该类声明中没有此类型的注释,则将在该类的超类中自动查询该注释类型。此过程会重复进行,直到找到此类型的注释或到达了该类层次结构的顶层 (Object) 为止。如果没有超类具有该类型的注释,则查询将指示当前类没有这样的注释。
注意,如果使用注释类型注释类以外的任何事物,此元注释类型都是无效的。还要注意,此元注释仅促成从超类继承注释;对已实现接口的注释无效。