生活随笔
收集整理的這篇文章主要介紹了
SpringApplication.run做了哪些事情
小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
URL
https://mp.weixin.qq.com/s/uP4seo__qYMJMzmbWyUUnA?tdsourcetag=s_pctim_aiomsg
SpringApplication.run
- 總共做了兩件事情,如下源碼
- 穿件SpringApplication對(duì)象
- 利用創(chuàng)建好的對(duì)象調(diào)用run方法
public static ConfigurableApplicationContext
run(Object source
, String
... args
) {return run(new Object[] { source
}, args
);}
public static ConfigurableApplicationContext
run(Object
[] sources
, String
[] args
) {return new SpringApplication(sources
).run(args
);}
- 此處開(kāi)始分成兩個(gè)部分,一部分:SpringApplication(sources)進(jìn)行SpringApplication的初始化工作,包括各種配置的初始化,listener初始化等 二部分:run(args)執(zhí)行run方法啟動(dòng)
public SpringApplication(Object
... sources
) {initialize(sources
);}
private void initialize(Object
[] sources
) {if (sources
!= null
&& sources
.length
> 0) {this.sources
.addAll(Arrays
.asList(sources
));}this.webEnvironment
= deduceWebEnvironment();setInitializers((Collection
) getSpringFactoriesInstances(ApplicationContextInitializer
.class));setListeners((Collection
) getSpringFactoriesInstances(ApplicationListener
.class));this.mainApplicationClass
= deduceMainApplicationClass();}
private Class
<?> deduceMainApplicationClass() {try {StackTraceElement
[] stackTrace
= new RuntimeException().getStackTrace();for (StackTraceElement stackTraceElement
: stackTrace
) {if ("main".equals(stackTraceElement
.getMethodName())) {return Class
.forName(stackTraceElement
.getClassName());}}}catch (ClassNotFoundException ex
) {}return null
;}
- 在初始化步驟中
- 步驟1 保存主配置信息
- 步驟2 判斷當(dāng)前是否是web應(yīng)用
- 步驟3中可以看到方法getSpringFactoriesInstances作用在于通過(guò)到路徑META_INF/spring.factories配置中所有ApplicationContextinitializer配置信息的list,接著通過(guò)initializers 將配置信息保存
- 步驟4 中同步驟3 一致,只不過(guò)這次獲取的配置類(lèi)型不同,連調(diào)用的方法都是一樣的,這次獲取的是ApplicationListener類(lèi)型的配置,之后保存
- 步驟5 中的deduceMainApplicationClass 方法在尋址一個(gè)包含main方法的配置類(lèi),如上部分代碼,也就是我們自己寫(xiě)的啟動(dòng)類(lèi)
- 第二部分則是運(yùn)行對(duì)應(yīng)的run方法:
public ConfigurableApplicationContext
run(String
... args
) {StopWatch stopWatch
= new StopWatch();stopWatch
.start();ConfigurableApplicationContext context
= null
;FailureAnalyzers analyzers
= null
;configureHeadlessProperty();SpringApplicationRunListeners listeners
= getRunListeners(args
);listeners
.starting();try {ApplicationArguments applicationArguments
= new DefaultApplicationArguments(args
);ConfigurableEnvironment environment
= prepareEnvironment(listeners
,applicationArguments
);Banner printedBanner
= printBanner(environment
);context
= createApplicationContext();analyzers
= new FailureAnalyzers(context
);prepareContext(context
, environment
, listeners
, applicationArguments
,printedBanner
);refreshContext(context
);afterRefresh(context
, applicationArguments
);listeners
.finished(context
, null
);stopWatch
.stop();if (this.logStartupInfo
) {new StartupInfoLogger(this.mainApplicationClass
).logStarted(getApplicationLog(), stopWatch
);}return context
;}catch (Throwable ex
) {handleRunFailure(context
, listeners
, analyzers
, ex
);throw new IllegalStateException(ex
);}}
private ConfigurableEnvironment
prepareEnvironment(SpringApplicationRunListeners listeners
,ApplicationArguments applicationArguments
) {ConfigurableEnvironment environment
= getOrCreateEnvironment();configureEnvironment(environment
, applicationArguments
.getSourceArgs());listeners
.environmentPrepared(environment
);if (!this.webEnvironment
) {environment
= new EnvironmentConverter(getClassLoader()).convertToStandardEnvironmentIfNecessary(environment
);}return environment
;}
此處先調(diào)用getRunListeners方法,同之前一樣,是獲取META_INF/Spring.factories文件中的配置信息,配置信息類(lèi)型是:SpringApplicationRunListeners在得到對(duì)應(yīng)的配置信息后,調(diào)用gstarting方法,改方法會(huì)去循環(huán)調(diào)用剛才獲取到的所有配置,并且觸發(fā)SpringApplicationRunListener中的starting事件,并且是異步的形式觸發(fā)接著封裝我們的命令行參數(shù),也就是我們main方法中傳入的args參數(shù)封裝成對(duì)應(yīng)的ApplicationArguments,此處步驟會(huì)先準(zhǔn)備對(duì)應(yīng)環(huán)境,主要是我們?cè)谂渲玫呐渲眯畔⒌鸟{照,在完成環(huán)境準(zhǔn)備之后在listeners.environmentPrepared(environment); 方法中會(huì)回調(diào)SpringApplicationRunListener中的environmentPrepared 事件,也是同樣的異步的方式觸發(fā)這個(gè)步驟pringBanner,啟動(dòng)時(shí)候banner的打印,可以自定義自步驟中的圖形createApplicationContext方法會(huì)更具我們之前環(huán)境判斷信來(lái)是web環(huán)境還是其他決定創(chuàng)建web還是普通的IOC容器此步驟中有多個(gè)功能 將environment上下文環(huán)境信息保存早ioc容器中執(zhí)行applyInitializers 方法,改方法會(huì)遍歷之前保存的ApplicationContextInitializer的initialize()事件在contextPerpared中遍歷SpringApplicationRunListener中的ContextPrepared()事件最后在contextLoaded方法中回調(diào)SpringApplicationRunListener中的ContextLoaded()事件 refreshContext顧名思義,刷新容器,進(jìn)行組件的掃描創(chuàng)建,加載等afterRefresh從IOC容器中獲取所有ApplicationRunner和CommandLineRunner遍歷所有runner并且調(diào)用callRunner方法回調(diào)用,先調(diào)用ApplicationRunner,在調(diào)用CommandLineRunnerfinished方法中遍歷SpringApplicationRunListener中的finished()事件最后返回context ioc容器
總結(jié)
- SpringApplication.run一共做了兩件事,一件是創(chuàng)建SpringApplication對(duì)象,在該對(duì)象初始化時(shí),找到配置的事件監(jiān)聽(tīng)器,并保存起來(lái).第二件事就是運(yùn)行run方法,此時(shí)會(huì)將剛才保存的事件監(jiān)聽(tīng)器根據(jù)當(dāng)前時(shí)機(jī)觸發(fā)不同的事件,比如容器初始化,容器創(chuàng)建完成等.同時(shí)也會(huì)刷新IoC容器,進(jìn)行組件的掃描、創(chuàng)建、加載等工作.
總結(jié)
以上是生活随笔為你收集整理的SpringApplication.run做了哪些事情的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。