前兩篇文章咱聊了深刻了解了 Spring 註解編程一些原理,這篇文章咱們關注註解屬性方法,聊聊 Spring 爲註解的帶來的功能,屬性別名與覆蓋。java
在進入瞭解 Spring 註解屬性功能以前,咱們先看一個正常 Java 註解。git
在註解中,屬性方法與其餘類/接口方法寫法相似,可是存在一些區別。github
註解屬性方法的返回類型僅限爲八種基本類型(包裝類不支持),字符串,class,enum,Annotation以及前面類型的數組。spring
複習一下,java 八種基本類型分別爲,byte(字節型)、short(短整型)、int(整型)、long(長整型)、float(單精度浮點型)、double(雙精度浮點型)、boolean(布爾型)、char(字符型)。編程
其次,註解屬性方法可使用 default
設置默認值。若是沒有設置默認值,聲明註解時必須顯式設置屬性,不然編譯將會出錯。數組
另外 Java 註解沒法繼承類,也沒法實現接口。app
在 Spring 中,有一些註解,使用不一樣屬性方法,卻能到達相同結果。典型的如 RequestMapping
。ide
在 WEB 項目中,設置 url 路徑,咱們能夠在方法是這樣聲明:url
@RequestMapping("hello") public String helloAnnotation() { 。。。。 }
上面方法本質使用註解
value
屬性。當註解聲明時只須要設置一個方法時,若是屬性方法爲 value,不須要使用 key=value 的語法,只須要直接設置屬性值便可。設計
另外也可使用 path
屬性方法設置。
@RequestMapping(path = "hello") public String helloAnnotation() { 。。。。 }
兩種方式,最後運行效果一致。
查看 RequestMapping
註解源碼,能夠發如今 value
與 path
屬性方法上使用 @AliasFor
,而且兩個互相指向對方。
Spring 4.2 加入 @AliasFor
註解,並使用 @AliasFor
從新更新 RequestMapping
等註解,爲它們內部帶來了別名的功能。
@AliasFor
使用方式在 Spring 中,@AliasFor
能夠在同一註解中使用,使用方法如 RequestMapping
註解。
這種方式,帶來含義明確屬性方法。如 RequestMapping
,path
屬性方法,這個屬性方法含義就比較明確,不一樣的人理解不會有誤差。而 value
屬性含義就不是很明確,不能一會兒就將它真正含義產生聯繫。
平常開發中,咱們也要避免 i,a,b 這些無心義的命名,儘可能使用含義明確的命名。這樣利用維護代碼的人理解。
第二點,同一註解屬性方法相互別名,這樣就兼容以前版本用法。
RequestMapping
註解若是僅新增 path
屬性,而後根據其解析 url 路徑,這樣就會致使升級 Spring 版本過程,運行錯誤的。
一個好軟件版本須要時向前兼容,如 JDK 8 兼容 JDK 6同樣。
另外 @AliasFor
註解還能夠做用與不一樣註解以前,典型的如 SpringBootApplication
註解。
SpringBootApplication#scanBasePackages
別名與 ComponentScan#basePackages
。設置前者間接爲後者賦值。
Spring Boot 就是使用 @Aliasfor
與組合註解功能,使用 SpringBootApplication
一個註解代替 Configuration
,EnableAutoConfiguration
,ComponentScan
。
使用 @AliasFor
註解,能夠作到別名的功能。
在 Spring 中別名能夠分爲如下幾類:
以上三類都須要知足如下條件:
不然運行過程當中將會出錯。
若是一個註解中的兩個成員經過 @AliasFor
聲明後互爲別名,那麼它們是顯式別名
。
顯示別名的關係如圖所示。
若是一個註解中的兩個或者更多成員經過@AliasFor
聲明去覆蓋同一個元註解的成員值,它們就是隱式別名
。
隱式別名如圖所示。
上圖中,@One
的 name
屬性與 nameAlias
別名與 @Two
nameAlias
屬性。因爲 @One
註解中並未直接使用 @AliasFor
,因此與 @One
註解隱式別名。
隱式別名相似於數學的等式。能夠將其看作如下推導過程。
@One.name=@Two.nameAlias @One.nameAlias=@Two.nameAlias 能夠推導出 @One.name=@One.nameAlias
若是一個註解中的兩個或者更多成員經過@AliasFor
聲明去覆蓋元註解中的不一樣成員,可是實際上由於覆蓋的傳遞性致使最終覆蓋的是元註解中的同一個成員,那麼它們就是傳遞隱式別名。
傳遞式隱式別名如圖所示。
這種類型涉及了多個註解,@One#name
別名了 @Two#nameAlias
屬性,而後在 @One#nameAlias
屬性又別名了 @Three#nameAliasThree
屬性。而後因爲 @Two#nameAlias
又別名了 @Three#nameAliasThree
屬性,這就致使 @One#name
與 @One#nameAlias
間接才生了關係。這種依靠傳遞性才生別名關係,稱爲 傳遞式隱式別名。
隱式別名相似於數學的等式。你們也能夠將其用上面等式推導。
屬性覆蓋指的是註解的一個成員覆蓋另外一個成員,最後二者成員屬性值一致。
屬性覆蓋能夠分爲三類:
當一個註解 @One
被元註解 @Two
標註,兩個註解存在一樣的屬性方法 name
。@Two#name
將會被 @One#name
屬性覆蓋。
兩個看似不來自不一樣註解的成員 name 指向了同一個成員 name。
顯示覆蓋就比較簡單了,使用 @AliasFor 註解以後,就成爲顯示覆蓋。
若是註解 @One#name
顯示覆蓋了 @Two#nameAlias
,而 @Two#nameAlias
顯示覆蓋了 @Three#nameAlias
,最後由於傳遞性,@One#name
實際覆蓋了@Three#nameAlias
。
Spring 4.2 新增 @AliasFor
註解,帶來一些特性。可是要注意的是僅僅存在 @AliasFor
不會執行任何語義別名。
底層原理能夠參考 AnnotationUtils
與 AnnotatedElementUtils
。
另外歡迎加入 Java 極客技術知識星球,獲取最新 Java 技術。