SpringBoot啓動源碼解析

SpringBoot啓動源碼精析

上篇:一步一步分析SpringBoot啓動源碼(一)

一、私有方法configureHeadlessProperty()
字面意思就是配置headless屬性,那麼headless是what?
Headless模式是系統的一種配置模式。在該模式下,系統缺少了顯示設備、鍵盤或鼠標。

Headless模式雖然不是我們願意見到的,但事實上我們卻常常需要在該模式下工作,尤其是服務器端程序開發者。因爲服務器(如提供Web服務的主機)往往可能缺少前述設備,但又需要使用他們提供的功能,生成相應的數據,以提供給客戶端(如瀏覽器所在的配有相關的顯示設備、鍵盤和鼠標的主機)。
二、SpringApplicationRunListeners listeners = getRunListeners(args);見方法名就知道它是幹什麼的,即獲取Spring應用的監聽器,一個完整的Spring應用運行監聽器如下圖:
這裏寫圖片描述
這裏要注意:
因爲我這裏分析的版本是1.5.13.RELEASE,而在2.0之後版本將整個過程做了調整且這塊不向下兼容。
1、SpringApplicationRunListener的獲取很前面的初始化器和監聽器一樣,通過解析META-INF/spring.factories中key爲org.springframework.boot.SpringApplicationRunListener的值,這裏我們發現只有一個,如下:

這裏寫圖片描述

然後通過反射實例化(先獲取public的構造器),而這裏只有一個構造器如下:

這裏寫圖片描述

接收兩個參數,第一個是我們正在啓動的Spring應用,第二個是args(通過main方法傳入的),在這個方法體首先分別把這兩個參數賦給成員變量,另外在這裏new了一個應用事件發射器,同時添加前面解析得到所有監聽器(已排序),目的是要給它當“觀衆”(事件接收者)。EventPublishingRunListener實例化,並其添加到SpringApplicationRunListeners(它是一個SpringApplicationRunListener的集合,即可以收集所有SpringApplicationRunListener),然後循環發佈事件。可以看出這裏是使用了觀察者設計模式,在之後閱讀源碼過程,會發現很多地方都使用了設計模式,如:策略模式等。

2.listeners.starting();標識着應用正式啓動。發佈正在啓動事件。SpringApplicationRunListeners要做的就是循環所有SpringApplicationRunListener(我們這裏只有一個)並調用starting方法發佈事件

這裏寫圖片描述

這裏實質調用的是EventPublishingRunListener裏面的starting,而在這裏它就使用了之前在構造它對象的時候一併初始化 的應用發射器SimpleApplicationEventMulticaster,這裏發送的事件名稱爲ApplicationStartedEvent(名字取的不好,所以已經標識deprecation,2.0版本已糾正)。而事件的接收者就是前面所提到”觀衆”,但是,在這裏它可不是給所有的發,而是過濾了一下,畢竟“己所不欲勿施於人”嘛,這裏過濾的原則就是由事件類型和事件源共同決定,舉個例子:就好比男人喜歡女人一樣,但不是隻要你是女人男的就喜歡,有的人說我喜歡四川的,而有的喜歡湖南的。
在這裏過濾前後對比如下:

這裏寫圖片描述

這裏提醒 Mcn打頭東西是我基於SpringBoot開發的一個自動化配置jar,沒用到的,直接無視。
在發送事件的時候,首先判斷了是否需要異步發送即有沒Executor,如果是異步的還有個異步錯誤處理器ErrorHandler,由於默認啓動這裏都沒有即同步啓動,直接跳到doInvokeListener方法,這裏調用了監聽器的onApplicationEvent方法,此時不難發現這個方法就是我們創建監聽器時所覆寫的方法。從第二個監聽器開始看即LoggingApplicationListener,在其onApplicationEvent方法通過if else if判斷當前來的是什麼時間類型(就好比來了個女的,你的看看她是不是來自四川一樣),這裏是啓動事件類型,這裏又調用了onApplicationStartingEvent方法,裏面獲取了Spring應用所使用的日誌系統,而具體使用的是哪種日誌實現由用戶定。

這裏寫圖片描述

BackgroundPreinitializer不處理該事件。
讀者可以想想爲什麼該監聽器不處理該事件,之前怎麼沒把它過濾掉?
DelegatingApplicationListener它也不處理該事件。不過讀者可以想想這個東西是幹嘛的?

LiquibaseServiceLocatorApplicationListener:class都沒有,不講了。
所有事件的發佈以及接受者的處理,模式都是一樣的,後面發佈的事件我就不一個個進去分析了,但是重要的還是要進去的,比如在上篇提到的ConfigFileApplicationListener

下篇:一步一步分析SpringBoot啓動源碼(三)

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章