Springboot啓動原理(二)

一、啓動方法

二、進入run方法,跟蹤下去發現他先調用一個初始化方法initialize

①sources 就是你的啓動對象

②deduceWebEnvironment()判斷是否是web環境,原理就是判斷如下的兩個類是否存在,存在就是web環境

③getSpringFactoriesInstances方法在springboot裏大量使用,他的作用是從spring的autoconfig包裏的META-INF下的spring.factories文件中加載指定接口的所有實現類。例如:getSpringFactoriesInstances(ApplicationContextInitializer.class)這句代碼,實際是去加載如下的類

④setInitializers 把加載到的類放到一個list裏頭去

⑤setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));這行代碼原理同③④,不做重複講解

⑥deduceMainApplicationClass 作用是獲取啓動類

三、看完初始化方法,接下來就是調用run方法了

public ConfigurableApplicationContext run(String... args) {
   //時鐘工具,用來計時
   StopWatch stopWatch = new StopWatch();
   stopWatch.start();
   //ApplicationContext的子類,比父類擁有更加豐富的方法,具體的以後分享spring原理的時候再說
   ConfigurableApplicationContext context = null;
   //異常報告,後面調用時候詳細說明
   FailureAnalyzers analyzers = null;
   //設置無頭模式,我也不太懂,自行百度,好像說是讓電腦自己模擬外接設備
   configureHeadlessProperty();
   //去spring.factories里加載SpringApplicationRunListener接口的實現類,其實這裏說是listener,實際上SpringApplicationRunListener更像一個發佈者publish,他的作用是發佈各自事件
   SpringApplicationRunListeners listeners = getRunListeners(args);
   //spring的觀察者模式模板,在springboot啓動過程用了很多這樣通知的地方,下一章將用一章來講解各個listener
   listeners.starting();
   try {
      ApplicationArguments applicationArguments = new DefaultApplicationArguments(
            args);
      //這一步獲取啓動命令裏的配置和具體要使用哪個環境的配置文件,就是根據sprring.active.profiles來加載配置文件。但是這裏要注意命令裏的配置會記錄到enviroment裏,但是配置文件,該行代碼僅僅是記錄你是用哪個文件。(說得夠清楚了吧)
      ConfigurableEnvironment environment = prepareEnvironment(listeners,
            applicationArguments);
      //打印banner
      Banner printedBanner = printBanner(environment);
      //根據是否是web項目創建不同的applicationcontext
      context = createApplicationContext();
      //這兒也是去spring.factories里加載好多失敗分析器,這個也單獨拿一個篇幅講吧。這篇主要是通體脈絡,細節會拆分到各個子篇幅裏去講。
      analyzers = new FailureAnalyzers(context);
      //這裏會把我們之前初始化時候加載的初始化類都執行一遍,後面專門開一個講每個初始化類的作用
      //以及會把啓動類加載到spring容器裏去,這樣我們第一章講的註解就能生效了。
      prepareContext(context, environment, listeners, applicationArguments,
            printedBanner);
      //調用spring的refresh方法
      refreshContext(context);
      //查找當前context中是否註冊有CommandLineRunner和ApplicationRunner,如果有則遍歷執行它們。
      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);
   }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章