品Spring:SpringBoot輕松取勝bean定義注冊的“第一階段”


上一篇文章強調了bean定義注冊占Spring應用的半壁江山。而且詳細介紹了兩個重量級的注冊bean定義的類。

今天就以SpringBoot為例,來看看整個SpringBoot應用的bean定義是如何注冊進容器的。

先來看看經典的啟動入口,如下圖01:


可以看到調用的是run方法,並把
主類(main或primary)作為第一個參數出入。

接下來要做的事情,就是順藤摸瓜,看看到底發生了什么,並確定下究竟哪些類被注冊了bean定義

此時,我就是一個快樂的小偵探,OK,走起。

上面的調用走到了這里,如下圖02:


可以看到把第一個參數(即主類)放入數組里,又調用了一個run方法,如下圖03:


使用第一個參數(即主類)去調用了構造函數,得到了實例對象,然后又調用了實例的run方法。

順着構造函數走下去,最終走到了這里,如圖04:


發現最終主類被,放到Set<Class<?>>類型的primarySources字段中。

編程新說注通過搜索全類,發現這個字段除了剛剛放入的主類外,再沒有放入其它類

接着再沿着run方法往下走,來到了這里,如下圖05:


首先定義了一個容器類的變量,然后創建容器類的實例,就是通過反射調用構造函數了。

然后就是准備容器,進入方法里看看,如下圖06:


在方法最后終於看到了我們期望的,即bean定義的注冊。

發現要注冊的資源是getAllSources()這個方法返回的,那就進去看看吧,如下圖07:


看到資源來自於primarySources字段和sources字段。第一個字段上文已經講了,只包含主類。

編程新說注:通過搜索全類,發現第二個字段sources是null因此它不包含資源

因此,真正獲取到的用於注冊bean定義的資源只有主類自己

那就打破砂鍋走到底,繼續吧。

再來看看load方法,如下圖08:


使用剛剛獲取到的資源創建了BeanDefinitionLoader類的實例。

這個類是SpringBoot定義的,類似於一個門面,因為它包含了所有注冊bean定義的方式。

這個類就是最后一步了,因此來看看,如下圖09:


首先是一個Object[]類型(之所以用Object,是因為資源類型有多種)的sources字段,用於存儲剛剛獲取的資源。

剩下四個都是用來注冊bean定義的,其中兩個上一篇已經講過。剩余兩個是處理xml和groovy的,一個已經過時,一個尚未流行。


最后再來看一眼,生成實例時調用的構造函數,如下圖10:


就是對五個字段的賦值或實例化,並無特別之處。(其實是有的,先賣個關子)

接下來就是根據資源的具體類型,使用四個bean定義注冊類中的一個來注冊bean定義。

這一通分析下來,推導出來的結論是:

截止到目前,只有主類自己被注冊了bean定義。

為了證明這一點,把日志級別改為DEBUG,如下圖11:


可以看出在源碼中,把資源數組進行了debug輸出。

最終輸出內容,如下圖12:


發現確實只注冊了主類自己,沒有其它。和我們分析的一樣,哈哈。

到現在prepareContext已經執行完畢了,接下來該執行的就是refreshContext了。

熟悉Spring容器的都知道,refresh其實就是容器的啟動了。

因此最后得出一個結論,對於“常規”的SpringBoot應用:

在Spring容器啟動前,只有應用的主類自己被注冊了bean定義。

What,are you kidding me?

Of course not。

那其它的那些bean定義是何時及如何注冊的呢?

且聽下回分解。

最后來看看主類的bean定義信息,作為一個小小的彩蛋吧。

如下圖13:


可以看出bean名稱符合
生成規則,bean定義使用了CGLIB生成了代理。

bean的一些屬性,單例、非抽象、非延遲加載、未明確定義自動裝配方式、作為自動裝配候選bean,非主要的等等。

bean定義的實現類是AnnotatedGenericBeanDefinition,可知是通過編程方式(而非jar包掃描)注冊的bean定義。

預祝,看過本文的人都有所收獲。若能轉發一下,則求之不得。

 

>>> 品Spring系列文章 <<<

 

品Spring:帝國的基石

品Spring:bean定義上梁山

品Spring:實現bean定義時采用的“先進生產力”

品Spring:注解終於“成功上位”

品Spring:能工巧匠們對注解的“加持”

品Spring:SpringBoot和Spring到底有沒有本質的不同?

品Spring:負責bean定義注冊的兩個“排頭兵”

 

作者是工作超過10年的碼農,現在任架構師。喜歡研究技術,崇尚簡單快樂。追求以通俗易懂的語言解說技術,希望所有的讀者都能看懂並記住。下面是公眾號和知識星球的二維碼,歡迎關注!

 

       

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM