在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 = Employee.class ; if(clazz.isAnnotationPresent(SpringBootApplication.class)){ System.out.println("true"); } }
上面這個測試用例執行將輸出true,也就是子類中能查找到@SpringBootApplication ,但同樣,你用上述代碼查找Employee類上是否有Spring的@Service注解時,會輸出false,至此你應該明白@Inherited注解的用意了吧。
經過這樣的分析,我們再來讀一下JDK的文檔,就會比較容易理解了,否則會覺的有些繞,下面列出 @interface注解的中文文檔:
指示注釋類型被自動繼承。如果在注釋類型聲明中存在 Inherited 元注釋,並且用戶在某一類聲明中查詢該注釋類型,同時該類聲明中沒有此類型的注釋,則將在該類的超類中自動查詢該注釋類型。此過程會重復進行,直到找到此類型的注釋或到達了該類層次結構的頂層 (Object) 為止。如果沒有超類具有該類型的注釋,則查詢將指示當前類沒有這樣的注釋。
注意,如果使用注釋類型注釋類以外的任何事物,此元注釋類型都是無效的。還要注意,此元注釋僅促成從超類繼承注釋;對已實現接口的注釋無效。