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早早初始化,是為了後面使用,看到後面還有乙個方法listeners.started()early initialization.
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的功能,動態載入配置...