原始碼分析SpringBoot啟動

2021-09-25 22:40:02 字數 4092 閱讀 9141

none, //不是web專案

servlet,//是web專案

reactive;之後新加的,響應式專案

...}

private collectiongetspringfactoriesinstances(classtype,

class> parametertypes, object... args)

首先得到classloader,這個裡面記錄了所有專案package的資訊、所有calss的資訊啊什麼什麼的,然後初始化各種instances,在排個序,ruturn之。

try

} }catch (classnotfoundexception ex)

return null;}

從方法棧stacktrace中,不斷讀取方法,通過名稱,當讀到「main」方法的時候,獲得這個類例項,return出去。

到這裡,所有初始化工作結束了,也找到了main方法,ruturn給run()方法,進行後續專案的專案啟動。

先上**:

stopwatch stopwatch = new stopwatch();

stopwatch.start();

collectionexceptionreporters = new arraylist<>();

configureheadlessproperty();

listeners.starting();

try

listeners.started(context);

} catch (throwable ex)

try

catch (throwable ex)

return context;}

首先開啟乙個計時器,記錄下這次啟動時間,咱們專案開啟 ***ms statred 就是這麼計算來的。

然後是一堆宣告,知道listeners.starting(),這個starting(),我看了一下原始碼注釋

called immediately when the run method has first started. can be used for very

early initialization.

早早初始化,是為了後面使用,看到後面還有乙個方法listeners.started()

private banner printbanner(configurableenvironment environment) 

resourceloader resourceloader = (this.resourceloader != null)

? this.resourceloader : new defaultresourceloader(getclassloader());

resourceloader, this.banner);

if (this.bannermode == mode.log)

}

接著開啟 exceptionreporters,用來支援啟動時的報錯。

接著就要準備往上下文中set各種東西了,看preparecontext()方法:

context.setenvironment(environment);

listeners.contextprepared(context);

if (this.logstartupinfo)

// add boot specific singleton beans

configurablelistablebeanfactory beanfactory = context.getbeanfactory();

if (printedbanner != null)

if (beanfactory instanceof defaultlistablebeanfactory)

// load the sources

setsources = getallsources();

assert.notempty(sources, "sources must not be empty");

load(context, sources.toarray(new object[0]));

listeners.contextloaded(context);}

首先把環境environment放進去,然後把resource資訊也放進去,再讓所有的listeners知道上下文環境。這個時候,上下文已經讀取yml檔案了所以這會兒引子中yml建立的引數,上下文讀到了配置資訊,又有點小激動了!接著看,向beanfactory註冊單例bean:乙個引數bean,乙個bannerbean。

preparecontext() 這個方法大概先這樣,然後回到run方法中,看看專案啟動還幹了什麼。

refreshcontext(context) 接著要重新整理上下問環境了,這個比較重要,也比較複雜,今天只看個大概,有機會另外寫一篇部落格,說說裡面的東西,這裡面主要是有個refresh()方法。看注釋可知,這裡面進行了bean工廠的建立,啟用各種beanfactory處理器,註冊beanpostprocessor,初始化上下文環境,國際化處理,初始化上下文事件廣播器,將所有bean的***註冊到廣播器(這樣就可以做到spring解耦後bean的通訊了吧)

總之,bean的初始化我們已經做好了,他們直接也可以很好的通訊。

listrunners = new arraylist<>();

runners.addall(context.getbeansoftype(commandlinerunner.class).values());

annotationawareordercomparator.sort(runners);

for (object runner : new linkedhashset<>(runners))

if (runner instanceof commandlinerunner) }}

最後run下這個,listeners.running(context);這會兒使用者自定義的事情也會被呼叫了。

ok,結束了。

今天只是大概看了下springboot啟動過程。有很多細節,比如refresh()都值得再仔細研究一下。springboot之所以好用,就是幫助我們做了很多配置,省去很多細節(不得不說各種stater真實讓我們傻瓜式使用了很多東西),但是同樣定位bug或者通過專案宣告週期搞點事情的時候會無從下手。所以,看看springboot原始碼還是聽有必要的。

SpringBoot原始碼分析

public class 第乙個引數 resourceloader 資源載入器 第二個引數 primarysources 載入的主要資源類 suppresswarnings public resourceloader resourceloader,class primarysources deduc...

Spring Boot 原始碼分析

1 專案初始化過程 springboot啟動類 springboot的啟動很簡單,如下 public static void main string args this.resourceloader resourceloader initialize sources private void ini...

spring boot原始碼分析

spring boot關鍵流程分析 進入preparecontext方法 轉化成beandefiniton類,註冊到spring 的beandefintionmap容器 enableautoconfigurationimportselector類,其父類裡面 這裡利用spring的功能,動態載入配置...