這篇文章我想和你聊一聊 spring的@Enable模塊驅動的實作原理,
在我們平時使用spring的程序中,如果想要加個定時任務的功能,那么就需要加注解@EnableScheduling,如果想使用異步的功能,那就要加@EnableScheduling注解,其實這類注解就是屬于@Enable模塊,
那么@Enable模塊到底有什么功能?
模塊是指具備相同領域的功能組件集合,組合所形成一個獨立的單元,比如Web MVC模塊、AspectJ代理模塊Caching快取模塊,JMX(Java管理擴展)、Async異步處理模塊等,所謂模塊裝配,簡而言之就是,通過@EnableXXX注解實作一個開關,這個開關決定是否開啟某個功能模塊的所有組件的自動化配置,
那么@EnableXXX注解是如何生效的?
其實@EnableXXX只是一個名字,通過這個名字讓人知道實作了什么功能,其實這個注解叫什么名字其實是無所謂的,就算不叫@EnableXXX都行,只不過spring內部都叫@EnableXXX,我們就習慣叫@Enable模塊,所以核心不是這個注解,而是注解實作的套路,
接下來我們來說說這個注解功能實作的套路
一般@EnableXXX注解是通過@Import實作具體的功能(@EnableXXX注解上加個@Import注解),@Import才是@EnableXXX起效果的核心功能,@Import大家都知道,就是往容器里面注入一個配置類,但是這個配置類可是有講究的,
這里我直接上原始碼,帶你看看@Import注解功能是如何實作的,

@Import注解的功能是在org.springframework.context.annotation.ConfigurationClassParser類processImports方法處理的,接下來我們就來解讀一下實作的核心部分,

首先判斷@Import注解匯入的是配置類有沒有實作ImportSelector介面,實作的話就就呼叫ImportSelector的selectImports方法,這個方法回傳的是一批配置類的全限定名,然后繼續決議這些配置類,

ImportSelector介面的作用其實就是往spring容器中再次注入一批配置類,
如果沒有實作ImportSelector介面,那么再判斷有沒有實作ImportBeanDefinitionRegistrar,有的話就會呼叫ImportBeanDefinitionRegistrar的registerBeanDefinitions方法,通過名字也可以判斷出,其實就是往spring容器注入一些BeanDefinition,

ImportBeanDefinitionRegistrar的作用其實很簡單,就是往spring容器注入一些BeanDefinition,如果不是很清楚BeanDefinition是什么,歡迎查看Spring bean到底是如何創建的?(上)這篇文章,有講解,
如果這兩個介面都沒有實作,那么就當時一個普通的配置類進行決議,
讀完@Import實作的原始碼,我們再來總結回顧@Import的作用,
@Import注解,就是匯入一個配置類,但是這個配置類分為不同的情況,如果這個配置類實作了ImportSelector介面,那么就會呼叫selectImports方法的實作,獲取一批配置類的全限定名,然后再決議配置類;如果實作了@Import注解匯入的配置類實作類ImportBeanDefinitionRegistrar,那么就會呼叫registerBeanDefinitions方法的實作,這個方法可以往容器中注入BeanDefinition;最后如果都沒實作,那么就按照一個普通的配置類來決議,
所以基于這么一套配置類決議的規則,就可以實作往容器中注入一些bean,通過這些bean來完成某塊功能的實作,
@EnbaleAsync注解的是如何起作用的
懂了@Enbale模塊驅動的基本原理,接下來我們舉個例子,來看看@EnbaleAsync注解是如何實作的,

@EnbaleAsync注解上通過@Import注解匯入了AsyncConfigurationSelector類
接下來我們進入這個類

一看原始碼,就發現繼承了AdviceModeImportSelector,其實這個類實作了ImportSelector介面,附上原始碼

其實這個對于ImportSelector介面的實作就是決議注解的屬性,然后拿到一個AdviceMode,再呼叫一個模板方法selectImports,這個方法主要子類來實作,所以我們來看看AsyncConfigurationSelector的實作,

這個adviceMode是注解@EnableAaync注解中的屬性mode(),你可以自己翻一下,默認是PROXY,所以這個方法其實就是回傳ProxyAsyncConfiguration類的全限定名,其實就是往容器中添加了ProxyAsyncConfiguration配置類,
我們進入這個配置類看一下

其實就是往容器中注入一個AsyncAnnotationBeanPostProcessor,通過名字可以看出這是一個BeanPostProcessor,也就是在bean的生命周期的某個節點來處理@Aysnc注解,如果有不懂BeanPostProcessor的同學可以看看Spring bean到底是如何創建的?(上)和 Spring bean到底是如何創建的?(下)這兩篇文章,里面有詳細的說明,至于AsyncAnnotationBeanPostProcessor的實作我們就不再繼續深究了,有興趣的同學可以自行點進去看看,
所以說白了,@EnbaleAsync注解的主要作用就是往容器中添加一個可以住了@Async注解的AsyncAnnotationBeanPostProcessor,在bean創建的某個階段起到作用,
看完@EnableAsync注解的實作,你也可以仿照這個注解的實作來自己實作一個@Enable來實作某個特定的功能,
本文到這里也就結束了,
如果我的文章對你有所幫助,還請幫忙點贊、在看、轉發一下,你的支持會激勵我輸出更高質量的文章,碼字不易,非常感謝!
如果你想聯系我,歡迎關注我的個人的微信公眾號三友的java日記,公眾號會持續推送優質的技術文章,期待與你一起進步,
最近花了一個月的時間,整理了這套并發編程系列的知識點,涵蓋了 volitile、synchronized、CAS、AQS、鎖優化策略、同步組件、資料結構、執行緒池、Thread、ThreadLocal,幾乎覆寫了所有的學習和面試場景,如圖,
檔案獲取方式:
鏈接:https://pan.baidu.com/s/129wZe3ywAUsjOqTU037Kmg
提取碼:aps9
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/482130.html
標籤:Java
上一篇:Spring Boot整合Swagger報錯:"this.condition" is null
下一篇:返回列表