激情久久久_欧美视频区_成人av免费_不卡视频一二三区_欧美精品在欧美一区二区少妇_欧美一区二区三区的

服務(wù)器之家:專注于服務(wù)器技術(shù)及軟件下載分享
分類導(dǎo)航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術(shù)|正則表達(dá)式|C/C++|IOS|C#|Swift|Android|VB|R語言|JavaScript|易語言|vb.net|

服務(wù)器之家 - 編程語言 - Java教程 - SpringBoot整個(gè)啟動(dòng)過程的分析

SpringBoot整個(gè)啟動(dòng)過程的分析

2021-07-21 14:29Super_PF Java教程

今天小編就為大家分享一篇關(guān)于SpringBoot整個(gè)啟動(dòng)過程的分析,小編覺得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來看看吧

前言

前一篇分析了springboot如何啟動(dòng)以及內(nèi)置web容器,這篇我們一起看一下springboot的整個(gè)啟動(dòng)過程,廢話不多說,正文開始。

正文

一、springboot的啟動(dòng)類是**application,以注解@springbootapplication注明。

?
1
2
3
4
5
6
@springbootapplication
public class cmsapplication {
 public static void main(string[] args) {
  springapplication.run(cmsapplication.class, args);
 }
}

springbootapplication注解是@configuration,@enableautoconfiguration,@componentscan三個(gè)注解的集成,分別表示springbean的配置bean,開啟自動(dòng)配置spring的上下文,組件掃描的路徑,這也是為什么*application.java需要放在根路徑的原因,這樣@componentscan掃描的才是整個(gè)項(xiàng)目。

二、該啟動(dòng)類默認(rèn)只有一個(gè)main方法,調(diào)用的是springapplication.run方法,下面我們來看一下springapplication這個(gè)類。

?
1
2
3
4
5
6
7
8
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);//sources為具體的cmsapplication.class類
 }
...

抽出其中兩個(gè)直接調(diào)用的run方法,可以看出靜態(tài)方法springapplication.run最終創(chuàng)建了一個(gè)springapplication,并運(yùn)行其中run方法。

查看起構(gòu)造方法:

?
1
2
3
4
5
6
7
8
9
10
public springapplication(object... sources) {
  this.bannermode = mode.console;
  this.logstartupinfo = true;
  this.addcommandlineproperties = true;
  this.headless = true;
  this.registershutdownhook = true;
  this.additionalprofiles = new hashset();
  this.initialize(sources);
 }
...

構(gòu)造方法設(shè)置了基礎(chǔ)值后調(diào)用initialize方法進(jìn)行初始化,如下:

?
1
2
3
4
5
6
7
8
9
10
private void initialize(object[] sources) {
  if (sources != null && sources.length > 0) {
   this.sources.addall(arrays.aslist(sources));
  }
  this.webenvironment = this.deducewebenvironment();
  this.setinitializers(this.getspringfactoriesinstances(applicationcontextinitializer.class));
  this.setlisteners(this.getspringfactoriesinstances(applicationlistener.class));
  this.mainapplicationclass = this.deducemainapplicationclass();
 }
...

初始化方法主要做了幾步:

1.將source放入springapplication的sources屬性中管理,sources是一個(gè)linkedhashset(),這意味著我們可以同時(shí)創(chuàng)建多個(gè)自定義不重復(fù)的application,但是目前只有一個(gè)。

2.判斷是否是web程序(javax.servlet.servletorg.springframework.web.context.configurablewebapplicationcontext都必須在類加載器中存在),并設(shè)置到webenvironment屬性中。

3.從spring.factories中找出applicationcontextinitializer并設(shè)置到初始化器initializers。

4.從spring.factories中找出applicationlistener,并實(shí)例化后設(shè)置到springapplication的監(jiān)聽器listeners屬性中。這個(gè)過程就是找出所有的應(yīng)用程序事件監(jiān)聽器。

5.找出的main方法的類(這里是cmsapplication),并返回class對(duì)象。

默認(rèn)情況下,initialize方法從spring.factories文件中找出的key為applicationcontextinitializer的類有:

  • org.springframework.boot.context.config.delegatingapplicationcontextinitializer
  • org.springframework.boot.context.contextidapplicationcontextinitializer
  • org.springframework.boot.context.configurationwarningsapplicationcontextinitializer
  • org.springframework.boot.context.web.serverportinfoapplicationcontextinitializer
  • org.springframework.boot.autoconfigure.logging.autoconfigurationreportlogginginitializer

key為applicationlistener的有:

  • org.springframework.boot.context.config.configfileapplicationlistener
  • org.springframework.boot.context.config.ansioutputapplicationlistener
  • org.springframework.boot.logging.loggingapplicationlistener
  • org.springframework.boot.logging.classpathloggingapplicationlistener
  • org.springframework.boot.autoconfigure.backgroundpreinitializer
  • org.springframework.boot.context.config.delegatingapplicationlistener
  • org.springframework.boot.builder.parentcontextcloserapplicationlistener
  • org.springframework.boot.context.fileencodingapplicationlistener
  • org.springframework.boot.liquibase.liquibaseservicelocatorapplicationlistener

三、springapplication構(gòu)造和初始化完成后,便是運(yùn)行其run方法

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
public configurableapplicationcontext run(string... args) {
  stopwatch stopwatch = new stopwatch();// 構(gòu)造一個(gè)任務(wù)執(zhí)行觀察器
  stopwatch.start();// 開始執(zhí)行,記錄開始時(shí)間
  configurableapplicationcontext context = null;
  failureanalyzers analyzers = null;
  this.configureheadlessproperty();
  // 獲取springapplicationrunlisteners,內(nèi)部只有一個(gè)eventpublishingrunlistener
  springapplicationrunlisteners listeners = this.getrunlisteners(args);
  // 封裝成springapplicationevent事件然后廣播出去給springapplication中的listeners所監(jiān)聽,啟動(dòng)監(jiān)聽
  listeners.starting();
  try {
   // 構(gòu)造一個(gè)應(yīng)用程序參數(shù)持有類
   applicationarguments applicationarguments = new defaultapplicationarguments(args);
   // 加載配置環(huán)境
   configurableenvironment environment = this.prepareenvironment(listeners, applicationarguments);
   banner printedbanner = this.printbanner(environment);
   // 創(chuàng)建spring容器(使用beanutils.instantiate)
   context = this.createapplicationcontext();
   // 若容器創(chuàng)建失敗,分析輸出失敗原因
   new failureanalyzers(context);
   // 設(shè)置容器配置環(huán)境,監(jiān)聽等
   this.preparecontext(context, environment, listeners, applicationarguments, printedbanner);
   // 刷新容器
   this.refreshcontext(context);
   this.afterrefresh(context, applicationarguments);
   // 廣播出applicationreadyevent事件給相應(yīng)的監(jiān)聽器執(zhí)行
   listeners.finished(context, (throwable)null);
   stopwatch.stop();// 執(zhí)行結(jié)束,記錄執(zhí)行時(shí)間
   if (this.logstartupinfo) {
    (new startupinfologger(this.mainapplicationclass)).logstarted(this.getapplicationlog(), stopwatch);
   }
   return context;// 返回spring容器
  } catch (throwable var9) {
   this.handlerunfailure(context, listeners, (failureanalyzers)analyzers, var9);
   throw new illegalstateexception(var9);
  }
 }

run方法過程分析如上,該方法幾個(gè)關(guān)鍵步驟如下:

1.創(chuàng)建了應(yīng)用的監(jiān)聽器springapplicationrunlisteners并開始監(jiān)聽

2.加載springboot配置環(huán)境(configurableenvironment),如果是通過web容器發(fā)布,會(huì)加載standardenvironment,其最終也是繼承了configurableenvironment,類圖如下 

SpringBoot整個(gè)啟動(dòng)過程的分析

可以看出,*environment最終都實(shí)現(xiàn)了propertyresolver接口,我們平時(shí)通過environment對(duì)象獲取配置文件中指定key對(duì)應(yīng)的value方法時(shí),就是調(diào)用了propertyresolver接口的getproperty方法。

3.配置環(huán)境(environment)加入到監(jiān)聽器對(duì)象中(springapplicationrunlisteners)

4.創(chuàng)建spring容器:configurableapplicationcontext(應(yīng)用配置上下文),我們可以看一下創(chuàng)建方法

?
1
2
3
4
5
6
7
8
9
10
11
protected configurableapplicationcontext createapplicationcontext() {
  class<?> contextclass = this.applicationcontextclass;
  if (contextclass == null) {
   try {
    contextclass = class.forname(this.webenvironment ? "org.springframework.boot.context.embedded.annotationconfigembeddedwebapplicationcontext" : "org.springframework.context.annotation.annotationconfigapplicationcontext");
   } catch (classnotfoundexception var3) {
    throw new illegalstateexception("unable create a default applicationcontext, please specify an applicationcontextclass", var3);
   }
  }
  return (configurableapplicationcontext)beanutils.instantiate(contextclass);
 }

方法會(huì)先獲取顯式設(shè)置的應(yīng)用上下文(applicationcontextclass),如果不存在,再加載默認(rèn)的環(huán)境配置(通過是否是web environment判斷),默認(rèn)選擇annotationconfigapplicationcontext注解上下文(通過掃描所有注解類來加載bean),最后通過beanutils實(shí)例化上下文對(duì)象,并返回,configurableapplicationcontext類圖如下

SpringBoot整個(gè)啟動(dòng)過程的分析

主要看其繼承的兩個(gè)方向:

  • lifecycle:生命周期類,定義了start啟動(dòng)、stop結(jié)束、isrunning是否運(yùn)行中等生命周期空值方法
  • applicationcontext:應(yīng)用上下文類,其主要繼承了beanfactory(bean的工廠類)。

5.回到run方法內(nèi),設(shè)置容器preparecontext方法,將listeners、environment、applicationarguments、banner等重要組件與上下文對(duì)象關(guān)聯(lián)

6.刷新容器,refresh()方法,初始化方法如下:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
public void refresh() throws beansexception, illegalstateexception {
  object var1 = this.startupshutdownmonitor;
  synchronized(this.startupshutdownmonitor) {
   this.preparerefresh();
   configurablelistablebeanfactory beanfactory = this.obtainfreshbeanfactory();
   this.preparebeanfactory(beanfactory);
   try {
    this.postprocessbeanfactory(beanfactory);
    this.invokebeanfactorypostprocessors(beanfactory);
    this.registerbeanpostprocessors(beanfactory);
    this.initmessagesource();
    this.initapplicationeventmulticaster();
    this.onrefresh();
    this.registerlisteners();
    this.finishbeanfactoryinitialization(beanfactory);
    this.finishrefresh();
   } catch (beansexception var9) {
    if (this.logger.iswarnenabled()) {
     this.logger.warn("exception encountered during context initialization - cancelling refresh attempt: " + var9);
    }
    this.destroybeans();
    this.cancelrefresh(var9);
    throw var9;
   } finally {
    this.resetcommoncaches();
   }
  }
 }

refresh()方法做了很多核心工作比如beanfactory的設(shè)置,beanfactorypostprocessor接口的執(zhí)行、beanpostprocessor接口的執(zhí)行、自動(dòng)化配置類的解析、spring.factories的加載、bean的實(shí)例化、條件注解的解析、國(guó)際化的初始化等等。這部分內(nèi)容會(huì)在之后的文章中分析。

7.廣播出applicationreadyevent,執(zhí)行結(jié)束返回configurableapplicationcontext。

至此,springboot啟動(dòng)完成,回顧整體流程,springboot的啟動(dòng),主要?jiǎng)?chuàng)建了配置環(huán)境(environment)、事件監(jiān)聽(listeners)、應(yīng)用上下文(applicationcontext),并基于以上條件,在容器中開始實(shí)例化我們需要的bean。

總結(jié)

以上就是這篇文章的全部?jī)?nèi)容了,希望本文的內(nèi)容對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,謝謝大家對(duì)服務(wù)器之家的支持。如果你想了解更多相關(guān)內(nèi)容請(qǐng)查看下面相關(guān)鏈接

原文鏈接:https://blog.csdn.net/u011961421/article/details/80227453

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 成人av一区二区免费播放 | 视频一区二区精品 | 神秘电影91 | 国产精品嘿咻嘿咻在线播放 | 成人黄色小视频网站 | 日韩一级精品 | 久草手机视频在线观看 | asian附近女人裸体pics | 色屁屁xxxxⅹ免费视频 | 爱视频福利 | 午夜视频在线免费播放 | 婷婷精品国产一区二区三区日韩 | www69xxx| 午夜激情视频网站 | 欧美精品一区二区三区在线 | 毛片午夜 | 国产精品久久久久国产精品三级 | 一分钟免费观看完整版电影 | 亚洲成人欧美 | 日本不卡一区二区三区在线观看 | 日本成人在线免费 | 激情综合在线 | 国产成年人在线观看 | 日韩激情在线视频 | 加勒比婷婷色综合久久 | 99国产精品白浆在线观看免费 | 91社影院在线观看 | 一级做受毛片免费大片 | 久久久一区二区三区精品 | 万圣街在线观看免费完整版 | 午夜精品久久久久久久久久久久久蜜桃 | 国产免费最爽的乱淫视频a 午夜精品久久久久久久99热浪潮 | 亚a在线| 中国av一级片 | 成人免费一区二区三区视频网站 | 久久人人av | 毛片免费看网站 | www.99久| 人人舔人人插 | 成人在线第一页 | 国产成人在线免费视频 |