亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 開發 > Java > 正文

SpringBoot整個啟動過程的分析

2024-07-14 08:43:42
字體:
來源:轉載
供稿:網友

前言

前一篇分析了SpringBoot如何啟動以及內置web容器,這篇我們一起看一下SpringBoot的整個啟動過程,廢話不多說,正文開始。

正文

一、SpringBoot的啟動類是**application,以注解@SpringBootApplication注明。

@SpringBootApplicationpublic class CmsApplication { public static void main(String[] args) {  SpringApplication.run(CmsApplication.class, args); }}

SpringBootApplication注解是@Configuration,@EnableAutoConfiguration,@ComponentScan三個注解的集成,分別表示Springbean的配置bean,開啟自動配置spring的上下文,組件掃描的路徑,這也是為什么*application.java需要放在根路徑的原因,這樣@ComponentScan掃描的才是整個項目。

二、該啟動類默認只有一個main方法,調用的是SpringApplication.run方法,下面我們來看一下SpringApplication這個類。

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類 }...

抽出其中兩個直接調用的run方法,可以看出靜態方法SpringApplication.run最終創建了一個SpringApplication,并運行其中run方法。

查看起構造方法:

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); }...

構造方法設置了基礎值后調用initialize方法進行初始化,如下:

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是一個LinkedHashSet(),這意味著我們可以同時創建多個自定義不重復的Application,但是目前只有一個。 

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

3.從spring.factories中找出ApplicationContextInitializer并設置到初始化器initializers。 

4.從spring.factories中找出ApplicationListener,并實例化后設置到SpringApplication的監聽器listeners屬性中。這個過程就是找出所有的應用程序事件監聽器。 

5.找出的main方法的類(這里是CmsApplication),并返回Class對象。

默認情況下,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構造和初始化完成后,便是運行其run方法

public ConfigurableApplicationContext run(String... args) {  StopWatch stopWatch = new StopWatch();// 構造一個任務執行觀察器  stopWatch.start();// 開始執行,記錄開始時間  ConfigurableApplicationContext context = null;  FailureAnalyzers analyzers = null;  this.configureHeadlessProperty();  // 獲取SpringApplicationRunListeners,內部只有一個EventPublishingRunListener  SpringApplicationRunListeners listeners = this.getRunListeners(args);  // 封裝成SpringApplicationEvent事件然后廣播出去給SpringApplication中的listeners所監聽,啟動監聽  listeners.starting();  try {   // 構造一個應用程序參數持有類   ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);   // 加載配置環境   ConfigurableEnvironment environment = this.prepareEnvironment(listeners, applicationArguments);   Banner printedBanner = this.printBanner(environment);   // 創建Spring容器(使用BeanUtils.instantiate)   context = this.createApplicationContext();   // 若容器創建失敗,分析輸出失敗原因   new FailureAnalyzers(context);   // 設置容器配置環境,監聽等   this.prepareContext(context, environment, listeners, applicationArguments, printedBanner);   // 刷新容器   this.refreshContext(context);   this.afterRefresh(context, applicationArguments);   // 廣播出ApplicationReadyEvent事件給相應的監聽器執行   listeners.finished(context, (Throwable)null);   stopWatch.stop();// 執行結束,記錄執行時間   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方法過程分析如上,該方法幾個關鍵步驟如下:

1.創建了應用的監聽器SpringApplicationRunListeners并開始監聽

2.加載SpringBoot配置環境(ConfigurableEnvironment),如果是通過web容器發布,會加載StandardEnvironment,其最終也是繼承了ConfigurableEnvironment,類圖如下 

SpringBoot,啟動過程

可以看出,*Environment最終都實現了PropertyResolver接口,我們平時通過environment對象獲取配置文件中指定Key對應的value方法時,就是調用了propertyResolver接口的getProperty方法。

3.配置環境(Environment)加入到監聽器對象中(SpringApplicationRunListeners)

4.創建Spring容器:ConfigurableApplicationContext(應用配置上下文),我們可以看一下創建方法

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); }

方法會先獲取顯式設置的應用上下文(applicationContextClass),如果不存在,再加載默認的環境配置(通過是否是web environment判斷),默認選擇AnnotationConfigApplicationContext注解上下文(通過掃描所有注解類來加載bean),最后通過BeanUtils實例化上下文對象,并返回,ConfigurableApplicationContext類圖如下

SpringBoot,啟動過程

主要看其繼承的兩個方向: 

  • LifeCycle:生命周期類,定義了start啟動、stop結束、isRunning是否運行中等生命周期空值方法 
  • ApplicationContext:應用上下文類,其主要繼承了beanFactory(bean的工廠類)。

5.回到run方法內,設置容器prepareContext方法,將listeners、environment、applicationArguments、banner等重要組件與上下文對象關聯

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

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的設置,BeanFactoryPostProcessor接口的執行、BeanPostProcessor接口的執行、自動化配置類的解析、spring.factories的加載、bean的實例化、條件注解的解析、國際化的初始化等等。這部分內容會在之后的文章中分析。

7.廣播出ApplicationReadyEvent,執行結束返回ConfigurableApplicationContext。

至此,SpringBoot啟動完成,回顧整體流程,Springboot的啟動,主要創建了配置環境(environment)、事件監聽(listeners)、應用上下文(applicationContext),并基于以上條件,在容器中開始實例化我們需要的Bean。

總結

以上就是這篇文章的全部內容了,希望本文的內容對大家的學習或者工作具有一定的參考學習價值,謝謝大家對VeVb武林網的支持。


注:相關教程知識閱讀請移步到JAVA教程頻道。
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
91九色在线视频| 国产精品99久久久久久www| 92看片淫黄大片看国产片| 欧美精品成人在线| 国产精品白嫩初高中害羞小美女| 国产欧美在线视频| 国内成人精品视频| 亚洲激情在线视频| 亚洲精品久久久久中文字幕欢迎你| 国产精品久久9| 欧美电影在线观看高清| 欧美自拍视频在线| 亚洲美女av黄| 97av在线影院| 日韩毛片在线观看| 欧美另类精品xxxx孕妇| 粉嫩老牛aⅴ一区二区三区| 伊人伊成久久人综合网小说| 激情亚洲一区二区三区四区| 国产不卡av在线免费观看| 丝袜亚洲欧美日韩综合| 中文字幕视频一区二区在线有码| 亚洲自拍小视频| 国产91精品久| 欧美一区二区三区……| 日本19禁啪啪免费观看www| 日本成人激情视频| 国产精品偷伦免费视频观看的| 中文字幕在线精品| 成人一区二区电影| 91久久在线视频| 精品久久久久久久久中文字幕| 亚洲精品动漫久久久久| 国产在线999| 亚洲精品99久久久久| 久久精品中文字幕免费mv| 日韩精品在线观看视频| 日韩va亚洲va欧洲va国产| 欧美中文字幕视频| 成人黄色影片在线| 深夜福利91大全| 久久大大胆人体| 国产97在线观看| 欧美日韩国产成人在线| 最近更新的2019中文字幕| 国产成人精彩在线视频九色| 91精品国产高清| 日产精品99久久久久久| 日韩成人av在线| 欧美巨猛xxxx猛交黑人97人| 欧美成年人在线观看| 国产精品美女午夜av| 国产不卡av在线免费观看| 久久九九热免费视频| 国产区精品视频| 中文字幕免费国产精品| 欧美激情喷水视频| 欧美巨猛xxxx猛交黑人97人| 一区二区三区日韩在线| 51午夜精品视频| 欧美高清在线观看| 日韩欧美亚洲综合| 国产一区二区三区视频| 午夜免费久久久久| 亚洲精品乱码久久久久久按摩观| 欧美一级bbbbb性bbbb喷潮片| 国产精品91免费在线| 亚洲成人精品在线| 精品少妇v888av| 国产欧美日韩中文字幕在线| 亚洲精品少妇网址| 国产一区二区黑人欧美xxxx| 狠狠色狠色综合曰曰| 成人免费观看49www在线观看| 亚洲人免费视频| 国内精品久久久久久久久| 久久视频中文字幕| 亚洲护士老师的毛茸茸最新章节| 国产香蕉精品视频一区二区三区| 成人黄色av免费在线观看| 日韩av中文在线| 亚洲免费av片| 国产精品wwwwww| 色在人av网站天堂精品| 色777狠狠综合秋免鲁丝| 97精品久久久中文字幕免费| x99av成人免费| 色伦专区97中文字幕| 成人免费视频xnxx.com| 国产成人在线精品| 国产91精品久久久久| 精品国产美女在线| 欧洲精品毛片网站| 久久精品2019中文字幕| 91精品国产777在线观看| 国产亚洲欧美视频| 欧美日韩国产91| 色噜噜亚洲精品中文字幕| 国产成人97精品免费看片| 欧美在线一级va免费观看| 亚洲精品av在线播放| 青草青草久热精品视频在线网站| 国产午夜精品理论片a级探花| 欧美日韩免费一区| 97婷婷大伊香蕉精品视频| 久久久久久久久久久av| 久久久91精品国产| 久久久久久久久久久av| 成人福利网站在线观看| 国产成人涩涩涩视频在线观看| 亚洲电影免费观看高清完整版| 久久久久久中文| 中文字幕日韩精品在线| 亚洲精品国产精品国产自| 亚洲午夜色婷婷在线| 欧美激情网友自拍| 亚洲国产精品热久久| 黑人巨大精品欧美一区二区一视频| 亚洲性无码av在线| 欧美在线观看日本一区| 国产香蕉一区二区三区在线视频| 日韩免费在线观看视频| 欧美三级欧美成人高清www| 在线成人一区二区| 亚洲va久久久噜噜噜| 中文字幕免费精品一区高清| 国产精品久久久91| 精品国产视频在线| 日韩av中文字幕在线免费观看| 日韩欧美亚洲成人| 成人444kkkk在线观看| 韩国国内大量揄拍精品视频| 丁香五六月婷婷久久激情| 久久久久中文字幕2018| 欧美麻豆久久久久久中文| 欧美亚洲成人xxx| 欧美日韩综合视频| 日韩欧美综合在线视频| 国产精品成人免费视频| 欧美乱大交做爰xxxⅹ性3| 国产精品高清免费在线观看| 国产成人精品综合久久久| 日韩一区二区三区xxxx| 成人欧美一区二区三区黑人| 欧美人与性动交a欧美精品| 91精品国产自产在线老师啪| 韩剧1988免费观看全集| 91产国在线观看动作片喷水| 亚洲一二在线观看| 久久综合国产精品台湾中文娱乐网| 国产91在线播放精品91| 亚洲色图35p| 精品美女国产在线| 亚洲r级在线观看| 亚洲精品美女在线| 国产婷婷97碰碰久久人人蜜臀| 欧美日韩免费在线| 欧美性xxxx在线播放| 大胆欧美人体视频| 国产精品嫩草影院一区二区| 欧美在线影院在线视频| y97精品国产97久久久久久| 日韩av一区二区在线| 国产精品久久久久久久午夜|