spring boot 啟動(dòng)源碼閱讀(一)

? ? ? 相對(duì)于spring mvc,spring boot并不是一個(gè)新的框架,給人最直觀的感受就是不需要spring mvc那樣寫一堆配置,因?yàn)樽隽舜罅康淖詣?dòng)化配置,當(dāng)然這只是最直觀的感受。所以我們來看看boot(以下spring boot簡稱boot)的啟動(dòng)過程,試圖去了解內(nèi)部到底做了什么。文中若有錯(cuò)誤之處,請(qǐng)指正。


? ? ? 這里框架demo的項(xiàng)目搭建這里就不展示了,比較簡單。我們先從入口類開始,例子中的入口類展示如下,

啟動(dòng)類

此類只有一個(gè)main方法,可以很清晰的看到有2個(gè)關(guān)鍵的信息點(diǎn):1.@SpringBootApplication注解,2.SpringApplication.run靜態(tài)方法。所以點(diǎn)開SpringApplication的源碼吧。源碼中第一步跟到static run方法。

SpringApplication中的run方法

可以看到里面做了兩件事情,一是構(gòu)造函數(shù),二是run方法。我們先看構(gòu)造函數(shù)做了什么。


一、構(gòu)造函數(shù)


org.springframework.boot.SpringApplication

兩個(gè)重載的構(gòu)造函數(shù),例子中調(diào)用的是第一個(gè),前幾行做了一些成員變量的初始化,我們先略去每個(gè)成員變量的具體意義,直接看這個(gè)方法this.initialize(sources);列子中參數(shù)sources為空,不用管。然后是this.webEnvironment=this.deduceWebEnvironment(); webEnvironment代表是否是web環(huán)境。

1.我們看deduceWebEnvironment方法是怎么做的。

? ? ? ? ? ? ? ? ? ? ??

判斷是否是web環(huán)境

其中WEB_ENVIRONMENT_CLASSES =newString[]{"javax.servlet.Servlet","org.springframework.web.context.ConfigurableWebApplicationContext"}; 該方法的關(guān)鍵的地方ClassUtils.isPresent主要就是根據(jù)WEB_ENVIRONMENT_CLASSES中的2個(gè)類名來查找classpath下面是否有2個(gè)class文件,如果都有webEnvironment則為true,否則為false。

2.接著我們看構(gòu)造函數(shù)中的下一行,this.setInitializers(this.getSpringFactoriesInstances(ApplicationContextInitializer.class));主要看getSpringFactoriesInstances。我們截取源碼中的改方法的代碼片段


片段1

我們可以知道片段1的getSpringFactoriesInstances()中的參數(shù)type為ApplicationContextInitializer.class對(duì)象。緊接著就調(diào)用它底下的一個(gè)重載方法。代碼2中是獲取當(dāng)前線程的一個(gè)類加載器。然后是3中SpringFactories.loadFactoryNames,此方法會(huì)查找classpath下面的META-INF/spring.factories文件中的類名,我們點(diǎn)開文件看下。


spring.factory


請(qǐng)注意classpath下面不止這一個(gè)spring.factorys文件,在這不全部展示,總之改方法會(huì)加載ApplicationContextInitializer對(duì)應(yīng)的一系列類名,如上圖中藍(lán)色部分。這些類都是ApplicationContextInitializer的實(shí)現(xiàn)類。然后圖片(片段1)中的方法4 就是把3中獲取到的類名利用反射構(gòu)造這些對(duì)象的實(shí)例。至此,setInitializers 方法中已經(jīng)獲取到以下這類的實(shí)例對(duì)象的集合。


ApplicationContextInitializer


3.輪到setListeners,跟setInitializers方法過程一樣,只不過參數(shù)為ApplicationListener.class。最終setListeners幫助SpringApplication獲取到了一系列ApplicationListener的實(shí)現(xiàn)類的對(duì)象的集合,具體哪些對(duì)象,看下圖。


ApplicationListener

好了,我們?cè)诨氐綐?gòu)造函數(shù),走到這里了,this.mainApplicationClass=this.deduceMainApplicationClass();此步驟比較簡單,就是獲取我們的入口類CamelliaApplication的class對(duì)象。

至此,構(gòu)造函數(shù)已經(jīng)全部走完,主要做的事情就是1,初始化一些變量,2,實(shí)例化ApplicationContextInitializer的一系列的子類 3,實(shí)例化ApplicationListener一系列的子類。3,獲取入口的class對(duì)象。


留下的疑問點(diǎn):1,構(gòu)造函數(shù)中初始化的成員變量的意義,2.得到ApplicationContextInitializer和ApplicationListener的一些列對(duì)象是干什么的。我們還有很長的路走,別急。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容