注解定義(來自百度百科):訓示編譯器如何對待您的自定義 Annotation,預設上編譯器會将Annotation資訊留在class檔案中,但不被虛拟機器讀取,而僅用于編譯器或工具程式運作時提供資訊。
随着零配置的流行,注解的使用也越來越大衆化,注解的學習也很有必要。最近學習了下Spring的幾個注解,這裡與大家分享下自己對注解的了解。
首先我們來看下@Controller這個注解的
源碼 : ? |
不難看出,注解的關鍵字是@interface,很像一個接口,是不能夠執行個體化的,然而我們在實際使用的時候,通常通過反射機制,得到注解接口的一個執行個體,進行邏輯處理,後面的樣例會看到這種使用。(命名為value的注解方法有一個比較特别的用法,後面會提到。)
它的主體部分,定義了一個value()方法,實際上,它不僅是一個方法定義,也是注解的一個屬性定義。我們使用注解進行标注的時候,是這樣的:@Controller(value="MyController"),而在解析判斷時,會通過controller.value()方法,得到這個具體的value值"MyController"。再看看value()後面跟着的default,這個default表面上的意思是預設值為某個值,實際上還有一個功效,表示value屬性可以不輸入。是以我們使用Controller的時候,可以直接@Controller這樣使用,不需要給定value,若去掉default,不指定value,會編譯失敗。
再看看這個注解定義前面的注解。@Target,顧名思義,就是指定目前注解使用的作用目标。如果大家使用Eclipse等開發工具,将滑鼠放到ElementType.TYPE處,會看到其注釋内容,大緻意思是說,這個注解要放到類、接口或者枚舉類型聲明的地方。也就是說,我們的@Controller注解隻能放到類、接口、枚舉定義前面,不能放到成員屬性、方法、參數等地方。大家可以跟進ElementType,這裡定義了“TYPE,FIELD,METHOD,PARAMETER,CONSTRUCTOR,LOCAL_VARIABLE,ANNOTATION_TYPE,PACKAGE”這麼些枚舉,根據注釋(或者從枚舉英文含義也不難猜測。這也從另一方面說明,合理的命名有助于提高代碼可讀性)很容易知道,注解可以實作注解到類檔案的各個地方。
@Retention(RetentionPolicy.RUNTIME),Retention可能不好猜,但是看到後面的RUNTIME,精神一震,猜測應該是和“運作時”有關。再檢視API幫助文檔,Retention“訓示注釋類型的注釋要保留多久”。這個保留多久,就要和RetentionPolicy(Retention的政策)配合使用了。Controller的Retention政策是運作時的,這樣在代碼運作時,可以通過反射獲得這個注解。這中政策的好處,具體實作案例可以參考Spring的bean掃描以及AOP攔截的注解實作(Spring配置檔案的component-scan base-package配置後,Spring bean工廠會逐個掃描包下所有類,根據其注解來生成相關bean。大家可以分析@Component、@Service、@Autowired等,其政策也是RUNTIME的)。
@Documented,如果需要通過javadoc工具文檔化時,會判斷這個注解,進而保留注釋(具體沒有實踐過,不瞎謅了)。
@Component這個注解放在Controller上面,可以看做“Controller同樣具有Component的作用”。實際上,目前的Spring掃描bean的時候,隻認準了Component注解的。我們會看到,@Service、@Repository上面也有@Component注解。說道這裡又不得不岔開下話題,來比照下@Service、@Controller、@Repository、@Component這幾個注解的差別了。理論上講,@Service是注解提供服務性質的bean上的,@Controller是注解MVC的C上的,@Repository是存儲層bean使用的,而@Component是注解不區分服務還是控制的bean。實際上,這幾類注解最終在Spring裡都是以bean形式放到bean工廠裡,沒有什麼差別對待。是以Spring掃描bean的時候,一律以@Component作為标記,@Service、@Controller、@Repository可以看做是一種功能預留:将來可能會對這三種注解的類做bean初始化時,做額外的增強型處理。
拆分了注解後,我們會發現注解也沒那麼神秘。接下來可以設計個屬于自己的注解了:
自定義注解:
|
注解使用類:
|
測試:
|
上面定義的value()在使用時,如果不設定其它屬性,隻設定value,可以這樣簡寫:@MyAnnotation("abc"),此時,value的值為"abc",其它取預設值。(不局限String類型。當然,MyAnnotation的其它方法需要提供default值。)
以上是一個簡單的樣例,大家可以修改Target,增減方法,實作自己需要的注解。
最後,歡迎大家拍磚。