自定義註解、使用反射操作註解

自定義註解

這是一篇前導文,爲後面打算寫的 Spring Boot 讀取不到啓動類中的自定義註解做鋪墊。

你既然都看到這篇文章了,想必比我都瞭解什麼是註解、註解能用來幹嘛。之前都對註解懷着“敬畏”的心態,覺得能自定義註解的人一定很厲害,確實的確如此,我見到過的那些人確實都非常厲害。不過話說回來了,註解也不是什麼牛鬼蛇神,它就是一個標籤,只不過是這個標籤保存在源代碼中,並且能被 annotation API 工具(我把它當做註解解析器)操作。如果只是定義一個註解,而不去寫它的解析器,那的確沒什麼卵用……

語法和規範

@Documented
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
public @interface Test {
    int value() ;
    int key() default 1;
}

上面就是最常見的註解的定義語法了,它用 @interface 關鍵字定義,註解中的屬性定義不太一樣,它用類似方法的形式,這些屬性要麼有默認值,要麼在使用註解時提供這些值,註解處理器其實就是利用反射來取到註解的屬性,然後再根據屬性值來具體做出相應處理。沒什麼,不要給自己設限。註解也會被編譯成 .class 文件

如果一個註解中沒有任何屬性,就被稱作標記註解(mark annotation)。

根據 Java Language Specification(JLS 9.6),註解的名字不能和類名或者接口名相同,原話如下:
It is a compile-time error if an annotation type has the same simple name as any of its enclosing classes or interfaces. 其實這也可以理解,畢竟都是以 .java 結尾嘛

所有的註解都直接繼承自 java.lang.annotation.Annotation(注意這貨是個接口),這也不難理解,Class 類中的 getAnnotations() 方法返回的都是 Annotation[] 類型的數組。

元註解

並不想去接受這些概念性質的東西,元註解是一種特殊的註解,它被設計用來解釋其他註解何時、何處起作用。說白了就是元註解專門負責新註解的創建,如上述你看到的 @Test 註解一樣。

Java 提供了四種元註解:

名稱 參數
@Target ElementType 類型的數組,指明註解能應用在何處,凡是你能想到的地方(類、方法聲明、參數、包甚至是局部變量)都能使用註解,具體在 ElementType 枚舉類中有定義
@Retention 指明註解在什麼級別保存該註解,參數爲 RetentionPolicy 枚舉類,可選值有 SOURCE(被編譯器丟棄)、CLASS(在 class 文件中可用,會被 JVM 丟棄)、RUNTIME(JVM 運行時也保留該註解,可通過反射的方式讀取該註解的信息),一般情況下我們都是選擇 RUNTIMR,你可以留心一下 Lombok 大多是在 SOURCE 級別
@Documented 此註解包含在 Javadoc 中
@Inheried 允許子類繼承父類中的註解

我們定義自己的註解的時候,需要用這些元註解來指明這個註解可以被用到哪裏、在哪個級別起作用。

註解中若定義了名爲 value 的元素,並且在應用該註解的時候,此元素是唯一一個需要被賦值的元素,那麼此時無需使用 “名-值” 對的這種語法,只需在括號中給出 value 元素所需的值即可。——《Java 編程思想》

註解處理器

上面也說了,光有註解沒卵用,註解處理器纔會讓註解發揮出作用。
未完待續!

參考文章:
[1.] Java註解(三) 自定義註解與提取註解

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章