最近斷更了一段時間,由於公司比較忙,週五的時候在公司作了一個關於Netty的分享,後續會總結一下分享出來!web
最近一段時間發現常常看到不少人,對Spring源碼比較感興趣,平常開發中,不管你作什麼什麼項目,大部分都離不開Spring生態的那一套東西,因此不少人對Spring底層源碼實現很感興趣,可是有些歷來沒有接觸過源碼的開發者,在看Spring源碼的過程當中確實及其難受的,爲何,大部分人看源碼基本都是debug一點一點去看的,最後發現,越追越離譜,越追越深,到最後都追到JDK源碼了,也沒有明白是什麼意思!spring
對於學習源碼,個人見解是,先去徹底的熟悉它的用法,想一下若是讓你來實現,你會怎麼實現!有了這些想法以後,再去看源碼去印證你本身的觀點,遠比你本身去死扣源碼快的多。編程
並且,我問過一些讀者還有同事,我發現有不少人,看源碼容易陷入一個誤區,就是剛開始看源碼就死扣着一個細節不放,非得搞懂,我並非說這樣看源碼有什麼不對,可是在沒有對整個框架有一個全局瞭解的狀況下,不要這樣看,你應該先把它的大致框架給搞清楚,在後再分功能一步一步的瞭解每個功能項!這樣作,首先你對整個框架的架構有了一個模糊的認識,再扣細節的途中有時候即便你不知道這個代碼在幹什麼,你也隱約能猜出來,再經過debug 與本身的猜想相互印證,最終達到事半功倍的效果。固然這個建議只針對剛開始看源碼的同窗,若是你看的源碼不少了,那麼你確定又本身的一套學習方法,能夠的話,能夠在留言區或者私聊做者一塊兒交流一下!緩存
爲了幫助一些萌新們或者想要了解Spring源碼的小夥伴,我會把Spring的一些大致邏輯分析一下,細節方面,後續做者也會分享,可是今天這一篇文章,只是爲了讓你瞭解整個Spring的骨架!架構
這張圖基本的歸納了Spring初始化bean的整個生命週期,包括你們大概熟悉的一些生命週期的回調,以及AOP或者不少大神都分析過的Spring解決循環依賴的三級緩存,看不懂不要緊,後面做者會帶着源碼一步一步的分析:app
/** * spring debug * @author huangfu */ public class SpringDebug { public static void main(String[] args) { AnnotationConfigApplicationContext app = new AnnotationConfigApplicationContext(SpringDebugConfig.class); } } 複製代碼
上面這一行代碼我估計使用過Spring的人都特別熟悉,若是不熟悉,那我勸你先學會使用,再去深究一些源碼的底層邏輯!框架
下面咱們看一下,他到底是如何一步一步的實例化bean,接管bean,而後執行各類生命週期類的!咱們先不妨猜想一下,spring再讀取這些bean的時候,關於bean的信息必定是存放在了某一個實體上,那麼這個實體是什麼呢?這個類就是BeanDefinition
那麼他存儲了什麼東西呢?咱們看一下它的子類AbstractBeanDefinition
感興趣的小夥伴本身點進去看一下,做者這裏只是爲了讓你們瞭解什麼是BeanDefinition
:編輯器
裏面定義這相似與這樣的屬性值,固然做者作截取了少數屬性,它裏面的屬性遠遠比這多得多,它的目的就是bean實例化的時候,須要的數據不須要再經過本身去反射獲取,而是再Spring初始化的時候所有讀取,須要的時候從這裏面拿就行,瞭解了bd的概念以後,咱們是否疑惑?他讀取以後存放在哪裏呢?答案是存放再beanFactory裏面,因此Spring初始化的時候確定會先實現一個bean工廠!進入到AnnotationConfigApplicationContext
裏面,你會發下並無初始化,在那初始化呢?衆所周知,一個類再初始化的時候會先加載父類的構造函數,因此咱們須要去看一下它的父類GenericApplicationContext
:函數
public GenericApplicationContext() {
//初始化bean的工廠 this.beanFactory = new DefaultListableBeanFactory(); } 複製代碼
果真不出我所料,它再父類裏面建立了bean工廠,工廠有了,咱們繼續回到AnnotationConfigApplicationContext
裏面往下看:發現它調用了一個this(),說明它調用了本身的空構造方法,因此,咱們進入看一下:源碼分析
public AnnotationConfigApplicationContext() {
//初始化讀取器 this.reader = new AnnotatedBeanDefinitionReader(this); //初始化掃描器 this.scanner = new ClassPathBeanDefinitionScanner(this); } 複製代碼
「至此咱們就能夠看對照上面那幅圖:初始化的時候bean工廠有了」
「而後再本身的空構造方法裏面有初始化了讀取器!」
那咱們繼續回到AnnotationConfigApplicationContext
構造方法裏面:
/** * 建立一個新的AnnotationConfigApplicationContext,從給定的帶註釋的類派生bean定義 * 並自動刷新上下文。 * @param annotatedClasses one or more annotated classes, * e.g. {@link Configuration @Configuration} classes */ public AnnotationConfigApplicationContext(Class<?>... annotatedClasses) { //讀取Spring內置的幾個的class文件轉換爲bd 而後初始化bean工廠 this(); //這一步就是將配置類Config進行了註冊並解析bd register(annotatedClasses); //這一步是核心,Spring的理解全在這一步,這一步理解了也就能夠說將Spring理解了70% //內部作一系列的操做如調用bean工廠的後置處理器 實例化類 調用 後置處理器的前置處理 初始化類 調用後置處理器的後置處理 註冊事件監聽等操做 //完成一個類從class文件變爲bean的生命週期 refresh(); } 複製代碼
下一步是調用register
方法,幹什麼呢?試想一下,有時候咱們的自動掃描配置是經過註解@ComponentScan("com.service")
來配置的,這個類通常在哪?對了,通常實在配置類中的!
@Configuration
@ComponentScan("com.service") public class SpringDebugConfig {} 複製代碼
爲了可以知道,咱們要掃描那些包下的類,咱們就必須先去解析配置類的BeanDefinition
,這樣才能獲取後續我們要解析的包,固然這個方法不光解析了掃描的包,還解析了其餘東西,本文不作講解!
好了,再往下走咱們就知道了咱們即將要掃描那些包下的類,讓他變成bean,那麼咱們繼續向下走,走到refresh();
這個方法不得了他是整個Springbean初始化的核心方法,瞭解了它也就可以瞭解Spring的實例化,回調等一些列的問題,咱們進去看看:
進來以後,咱們一個方法一個方法的分析作了什麼功能,首先是:
❝這裏是作刷新bean工廠前的一系列賦值操做,主要是爲前面建立的Spring工廠不少的屬性都是空的,這個方式是爲他作一些列的初始化值的操做!
❞
❝告訴子類刷新內部bean工廠 檢測bean工廠是否存在 判斷當前的bean工廠是否只刷新過一次,屢次報錯,返回當前使用的bean工廠,當該步驟爲xml時 會新建一個新的工廠並返回
❞
❝這裏是初始化Spring的bean容器,向beanFactory內部註冊一些本身自己內置的Bean後置處理器也就是一般說的BeanPostProcessor,這個方法其實也是再初始化工廠!
❞
❝容許在上下文子類中對bean工廠進行後處理,做用是在BeanFactory準備工做完成後作一些定製化的處理! 可是注意,你點進去是空方法,空方法覺得着什麼?意味着Spring的開發者但願調用者自定義擴展時使用!
❞
❝其實相信看名字,大部分讀者都可以猜出,他的目的是掃描非配置類的bd註冊到工廠裏面,掃描完成以後,開始執行全部的
❞BeanFactoryPostProcessors
,這裏出現了第一個擴展點,自定義實現BeanFactoryPostProcessors
的時候,他的回調時機是在Spring讀取了所有的BeanDefinition
以後調用的,具體的使用方法讀者自行百度!
❝這裏是註冊bean的後置處理器 也就是 beanPostProcessor 的實現 還有本身內置的處理器 注意這裏並無調用該處理器,只是將胡處理器註冊進來bean工廠! 不知道你們使用過
❞beanPostProcessor
接口這個擴展點嗎?他就是再這個方法裏面被註冊到Spring工廠裏面的,固然注意一下,他只是註冊進去了,並無執行!記住並無執行!
❝怎麼說呢,這個方法做者並不許備深究,由於他和本篇文章的意圖相違背,他的目的是作一個國際化操做也就是 i18n的資源初始化
❞
❝Spring爲咱們提供了對於事件編程的封裝,通常來講事件分爲三個角色,
❞事件廣播器
(發佈事件),事件監聽器
(監聽事件),事件源
(具體的事件信息)三個角色,這個方法的目的就是初始化事件的廣播器!
❝這裏又是一個擴展點,內部的方法爲空,Spring並無實現它,供調用者實現!
❞
❝註冊Spring的事件監聽器,上面已經說過了,這裏是初始化而且註冊事件監聽器
❞
❝這個方法是一個重點,他是爲了實例化全部剩餘的(非延遲初始化)單例。咱們所說的bean的實例化,注入,解決循環依賴,回調
❞beanPostProcessor
等操做都是再這裏實現的!
❝最後一步:發佈相應的事件。Spring內置的事件
❞
至此咱們完成了整個Spring初始化的生命週期骨架,這裏做者並無深究裏面的實現,只是給讀者搭建了一個架子,幫助讀者理清Spring的脈絡,裏面的填充須要讀者本身填充!如今回過頭去看那個圖,是否是就清晰多了?這裏我再把那個圖放出來,省得大家再翻上去!
好了,今天的文章到這裏也就結束了,做者閒暇時間整理了一份資料,你們有興趣能夠領取下!
才疏學淺,若是文章中理解有誤,歡迎大佬們私聊指正!歡迎關注做者的公衆號,一塊兒進步,一塊兒學習!