朱曄和你聊Spring系列S1E9:聊聊Spring的那些註解

用於給Bean設置描述;@Scope用於設置Bean的生命週期;@Primary

用於在定義了多個Bean的時候指定首選的Bean
  • 其它一些註解包括:@EventListener用於設置回調方法監聽Spring制定的以及自定義的各種事件;@EnableAspectJAutoProxy用於開啟支持AspectJ的 @Aspect切面配置支持,使用Spring Boot引入了AOP啟動器的話不需要顯式開啟
  • Spring Web註解

    Spring MVC的各種註解對應了Spring MVC各方面的功能,下面我們來了解一下:

    • 首先是三個定義了Bean特殊生命週期的複合註解:@RequestScope@SessionScope@ApplicationScope。在Web應用中,我們可能需要Bean跟隨請求、會話和應用程序的聲明週期來進行創建,這個時候可以直接使用這三個快捷的複合註解
    • 接下去可以看到各種 @XXXMapping的註解,分別用於配置HandlerMethod匹配到不同的Http Method,當然不使用這些快捷的註解也是可以的,直接使用@RequestMapping然後手動設置method
    • @ResponseStatus可以用到方法上也可以用到異常上,前者會直接使請求得到指定的響應代碼或原因(可以配合@ExceptionHandler使用),後者可以實現遇到指定異常的時候給出指定的響應代碼或原因,@ResponseBody我們實現Restful接口的時候(@RestController)最常用了,把返回內容(序列化後)輸出到請求體
    • Spring MVC給了我們各種註解方便我們從HTTP請求各種地方獲取參數,@RequestBody從請求體(處理複雜數據,比如JSON),@RequestHeader從請求頭,@CookieValue從cookie中,@SessionAttribute從會話中,@RequestAttribute從請求的Attribute中(比如過濾器和攔截器手動設置的一些臨時數據),@RequestParam從請求參數(處理簡單數據,鍵值對),@PathVariable從路徑片段,@MatrixAttribute矩陣變量允許我們採用特殊的規則在URL路徑後加參數(分號區分不同參數,逗號為參數增加多個值)
    • @ControllerAdvice是一個重要註解,允許我們在集中的地方配置控制器(有@RequestMapping的方法)相關的增強(@RestControllerAdvice也是差不多的,只是相當於為@ExceptionHandler加上了@ResponseBody)。那麼可以應用哪些增強呢?首先是可以用 @ExceptionHandler進行統一的全局異常處理;第二是 @InitBinder用來設置WebDataBinder,WebDataBinder用來自動綁定前臺請求參數到Model中;第三是 @ModelAttribute讓全局的@RequestMapping都能獲得在此處設置的鍵值對。當然,這裡說的@InitBinder和@ExceptionHandler也可以不定義在@ControllerAdvice內部(作為全局開啟),定義在Controller內部應用到某個Controller也是可以的
    • 其它還有一些註解比如:@CrossOrigin可以用到Controller或Method上(需要配合@RequestMapping)設置細粒度的跨域行為 在之前的文章中我們也提到,對於Spring MVC,定義自己的註解應用到參數、方法、控制器上,配合HandlerMethodArgumentResolver、XXAdvise、以及Interceptor實現具體的功能來使用太太常見了,幾乎所有的非業務橫切關注點,我們都不應該在方法實現中重複任何一行代碼。

    Spring Boot註解

    • 來看一下上下文相關的註解:
      @ConfigurationProperties很常用(配合 @EnableConfigurationProperties註解來設置需要啟用的配置類),用來自定義配置類和配置文件進行關聯;@DeprecatedConfigurationProperty用於標記廢棄的配置以及設置替代配置和告知廢棄原因;@ConfigurationPropertiesBinding用於指定自定義的轉換器用於配置解析的時的類型轉換; @NestedConfigurationProperty用於關聯外部的類型作為嵌套配置類
    • 再看看自動配置相關的註解,自動配置是Spring Boot最重要的特性,在之前的系列文章中我有提到一個觀點,IOC是好事情,但是把組件內部的一些默認配置以及組件和組件的組裝交給外部用戶來配置其實是不合理的,組件應當可以自動進行自我配置實現開箱急用,只有需要自定義組件的時候才要求外部來進行個性化配置:@EnableAutoConfiguration註解可以啟用自動配置,Spring Boot應用程序一般我們會直接使用複合註解@SpringBootApplication;@AutoConfigureOrder(值越小優先級越高)、@AutoConfigureAfter@AutoConfigureBefore用於設置自動配置類加載順序,以及精確控制加載依賴關係,有的時候我們的自動配置需要相互依賴或者會相互干擾,需要手動調節
    • 最後來看一下十幾種配置條件,用好這些註解是實現完善的自動配置的關鍵:@ConditionalOnBean用於僅當容器中已經包含指定的Bean類型或名稱時才匹配條件;@ConditionalOnClass僅當classpath上存在指定類時條件匹配;@ConditionalOnCloudPlatform僅當指定的雲平臺處於活動狀態時條件匹配;@ConditionalOnExpression依賴於SpEL表達式的值的條件元素的配置註解;@ConditionalOnJava基於應用運行的JVM版本的條件匹配;@ConditionalOnJndi基於JNDI可用和可以查找指定位置的條件匹配;@ConditionalOnMissingBean僅當容器中不包含指定的Bean類型或名稱時條件匹配;@ConditionalOnMissingClass僅當classpath上不存在指定類時條件匹配;@ConditionalOnNotWebApplication 僅當不是WebApplicationContext(非Web項目)時條件匹配,對應 @ConditionalOnWebApplication@ConditionalOnProperty是檢查指定的屬性是否具有指定的值;@ConditionalOnResource表示僅當 classpath 上存在指定資源時條件匹配;@ConditionalOnSingleCandidate
      僅當容器中包含指定的Bean類並且可以判斷只有單個候選者時條件匹配。其實所有這些實現原理都是擴展SpringBootCondition抽象類(實現之前提到的Condition接口),我們完全可以實現自己的條件註解(配合 @Conditional註解關聯到自己實現的SpringBootCondition)

    Spring Cloud註解

    在介紹本系列文章的第一篇中我們就提到了,Spring Cloud整齊劃一通過各種EnableXXX註解開啟某個功能,這裡就不對這些註解進行說明了,使用Spring Boot組件的功能非常簡單,基本就是引POM+EnableXXX+設置配置文件三部曲。

    • 首先是 Netflix包下的一些註解,各種EnableXXX就不說了,參考前一篇文章,之前沒介紹過 @RibbonClient,這個註解用來為負載均衡客戶端做一些自定義的配置,可以進一步配置或自定義從哪裡獲取服務端列表、負載均衡策略、Ping也就是服務鑑活策略等等
    • client包下的 @SpringCloudApplication之前文章中我們也沒有使用到,這是一個複合註解就是 @SpringBootApplication+ @EnableDiscoveryClient+
      @EnableCircuitBreaker,Spring Cloud那堆東西很多,還是自己親手定義一個一個功能的註解來的踏實; @LoadBalanced註解用於和RestTemplate配合使用構成一個負載均衡的Http客戶端,實現原理上其實這個註解是一個@Qualifier註解,Spring會為所有@LoadBalanced的RestTemplate加入一個LoadBalancerInterceptor(實現ClientHttpRequestInterceptor)實現負載均衡
    • sleuth包下面的註解和鏈路跟蹤相關,比較常用的是通過 @SpanName手動設置span的名稱,其它註解對於業務開發並不常用

    總結

    好了,寫了本文我發現我看到@已經Markdown的**就眼花,請點贊支持。本文我們通過代碼打印出了大部分Spring相關的註解,你也可以通過這個方式熟悉其它框架的註解(畢竟註解是框架賦予我們各種便捷功能的一個重要入口,對註解瞭解個八九成也往往可以對框架賦予我們的豐富功能瞭解六七成)。然後我們梳理了一下Spring相關的各種註解,其中主要需要關注的是幾方面:

    1. 元註解,也就是註解的註解
    2. Spring容器相關的一些註解,包括@Qualifier、@AliasFor、@Order等看似不重要但其實很重要的註解
    3. Spring Java配置相關的一些註解,包括條件註解
    4. Spring Boot自動配置相關的一些註解
    5. 很多註解可以同時應用到類型、方法、參數上,有的時候應用到不同的地方作用會略微不一樣,這個需要重點關注

    我們知道註解其實只是一個標識,註解如何起作用背後的實現原理還是比較多樣的,你可以進一步結合本文介紹的Spring的各種註解探尋一下背後實現的原理。


    分享到:


    相關文章: