Spring 註解編程之註解屬性別名與覆蓋

前兩篇文章咱聊了深刻了解了 Spring 註解編程一些原理,這篇文章咱們關注註解屬性方法,聊聊 Spring 爲註解的帶來的功能,屬性別名與覆蓋。java

註解屬性方法

在進入瞭解 Spring 註解屬性功能以前,咱們先看一個正常 Java 註解。git

annotation.png

在註解中,屬性方法與其餘類/接口方法寫法相似,可是存在一些區別。github

註解屬性方法的返回類型僅限爲八種基本類型(包裝類不支持),字符串,class,enum,Annotation以及前面類型的數組。spring

複習一下,java 八種基本類型分別爲,byte(字節型)、short(短整型)、int(整型)、long(長整型)、float(單精度浮點型)、double(雙精度浮點型)、boolean(布爾型)、char(字符型)。編程

其次,註解屬性方法可使用 default設置默認值。若是沒有設置默認值,聲明註解時必須顯式設置屬性,不然編譯將會出錯。數組

另外 Java 註解沒法繼承類,也沒法實現接口。app

Spring 屬性方法特性

在 Spring 中,有一些註解,使用不一樣屬性方法,卻能到達相同結果。典型的如 RequestMappingide

在 WEB 項目中,設置 url 路徑,咱們能夠在方法是這樣聲明:url

@RequestMapping("hello")
    public String helloAnnotation() {
    。。。。
    }

上面方法本質使用註解 value 屬性。當註解聲明時只須要設置一個方法時,若是屬性方法爲 value,不須要使用 key=value 的語法,只須要直接設置屬性值便可。設計

另外也可使用 path 屬性方法設置。

@RequestMapping(path = "hello")
    public String helloAnnotation() {
    。。。。
    }

兩種方式,最後運行效果一致。

查看 RequestMapping 註解源碼,能夠發如今 valuepath 屬性方法上使用 @AliasFor,而且兩個互相指向對方。

RequestMapping.png

Spring 4.2 加入 @AliasFor 註解,並使用 @AliasFor 從新更新 RequestMapping等註解,爲它們內部帶來了別名的功能。

@AliasFor 使用方式

在 Spring 中,@AliasFor 能夠在同一註解中使用,使用方法如 RequestMapping 註解。

這種方式,帶來含義明確屬性方法。如 RequestMappingpath 屬性方法,這個屬性方法含義就比較明確,不一樣的人理解不會有誤差。而 value 屬性含義就不是很明確,不能一會兒就將它真正含義產生聯繫。

平常開發中,咱們也要避免 i,a,b 這些無心義的命名,儘可能使用含義明確的命名。這樣利用維護代碼的人理解。

第二點,同一註解屬性方法相互別名,這樣就兼容以前版本用法。

RequestMapping 註解若是僅新增 path 屬性,而後根據其解析 url 路徑,這樣就會致使升級 Spring 版本過程,運行錯誤的。

一個好軟件版本須要時向前兼容,如 JDK 8 兼容 JDK 6同樣。

另外 @AliasFor 註解還能夠做用與不一樣註解以前,典型的如 SpringBootApplication註解。

SpringBootApplication.png

SpringBootApplication#scanBasePackages 別名與 ComponentScan#basePackages。設置前者間接爲後者賦值。

Spring Boot 就是使用 @Aliasfor 與組合註解功能,使用 SpringBootApplication一個註解代替 ConfigurationEnableAutoConfigurationComponentScan

Spring 註解屬性覆蓋與別名

使用 @AliasFor 註解,能夠作到別名的功能。

在 Spring 中別名能夠分爲如下幾類:

  1. 顯式別名(xplicit Aliases
  2. 隱式別名(Implicit Aliases
  3. 傳遞隱式別名(Transitive Implicit Aliases

以上三類都須要知足如下條件:

  1. 屬性類型相同
  2. 屬性方法必須存在默認值
  3. 屬性默認值必須相同

不然運行過程當中將會出錯。

顯式別名

若是一個註解中的兩個成員經過 @AliasFor聲明後互爲別名,那麼它們是顯式別名

顯示別名的關係如圖所示。

image.png

隱式別名

若是一個註解中的兩個或者更多成員經過@AliasFor聲明去覆蓋同一個元註解的成員值,它們就是隱式別名

隱式別名如圖所示。

image.png

上圖中,@Onename 屬性與 nameAlias 別名與 @Two nameAlias 屬性。因爲 @One 註解中並未直接使用 @AliasFor,因此與 @One 註解隱式別名。

隱式別名相似於數學的等式。能夠將其看作如下推導過程。

@One.name=@Two.nameAlias
@One.nameAlias=@Two.nameAlias
能夠推導出
@One.name=@One.nameAlias

傳遞式隱式別名

若是一個註解中的兩個或者更多成員經過@AliasFor聲明去覆蓋元註解中的不一樣成員,可是實際上由於覆蓋的傳遞性致使最終覆蓋的是元註解中的同一個成員,那麼它們就是傳遞隱式別名。

傳遞式隱式別名如圖所示。

image.png

這種類型涉及了多個註解,@One#name別名了 @Two#nameAlias屬性,而後在 @One#nameAlias 屬性又別名了 @Three#nameAliasThree 屬性。而後因爲 @Two#nameAlias又別名了 @Three#nameAliasThree 屬性,這就致使 @One#name@One#nameAlias 間接才生了關係。這種依靠傳遞性才生別名關係,稱爲 傳遞式隱式別名。

隱式別名相似於數學的等式。你們也能夠將其用上面等式推導。

屬性覆蓋

屬性覆蓋指的是註解的一個成員覆蓋另外一個成員,最後二者成員屬性值一致。

屬性覆蓋能夠分爲三類:

  1. 隱式覆蓋(Implicit Overrides
  2. 顯示覆蓋(Explicit Overrides
  3. 傳遞式顯式覆蓋(Transitive Explicit Overrides

隱式覆蓋

當一個註解 @One 被元註解 @Two 標註,兩個註解存在一樣的屬性方法 name@Two#name 將會被 @One#name 屬性覆蓋。

image.png

兩個看似不來自不一樣註解的成員 name 指向了同一個成員 name。

顯示覆蓋

顯示覆蓋就比較簡單了,使用 @AliasFor 註解以後,就成爲顯示覆蓋。

image.png

傳遞式顯式覆蓋

若是註解 @One#name 顯示覆蓋了 @Two#nameAlias,而 @Two#nameAlias 顯示覆蓋了 @Three#nameAlias,最後由於傳遞性,@One#name 實際覆蓋了@Three#nameAlias

image.png

總結

Spring 4.2 新增 @AliasFor註解,帶來一些特性。可是要注意的是僅僅存在 @AliasFor 不會執行任何語義別名。

底層原理能夠參考 AnnotationUtilsAnnotatedElementUtils

幫助文檔

  1. Attribute Aliases and Overrides
  2. 註解編程模型~~~~

其餘平臺.png

另外歡迎加入 Java 極客技術知識星球,獲取最新 Java 技術。

稿定設計導出20190713162903.png

相關文章
相關標籤/搜索