<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      SpringBoot啟動流程總結

      1.導語

      //以下是一個SpringBoot應用的標準入口:
      public static void main(String[] args) {
          SpringApplication.run(TestApplication.class, args);
      }
      
      //SpringApplication.run 內部是這樣的:先創建一個 SpringApplication 對象,然后調用他的run方法。
      public static ConfigurableApplicationContext run(Class<?>[] primarySources, String[] args) {
          return new SpringApplication(primarySources).run(args);
      }

       所以想要了解清楚 SpringBoot 啟動流程,相當于了解 SpringApplication 的 構造方法 和 run方法。

       

      2.構造方法詳解

      public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {
      
          this.resourceLoader = resourceLoader;
          Assert.notNull(primarySources, "PrimarySources must not be null");
          this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources));
      
          // 判斷應用類型,會有三種情況:
          // NONE:非web應用
          // SERVLET:普通web應用
          // REACTIVE:響應式web應用
          this.webApplicationType = WebApplicationType.deduceFromClasspath();
      
          // 從 META-INF/spring.factories 文件中獲取如下內容
          // 獲取 注冊初始化器:在 run 方法中的 createBootstrapContext(); 里會被使用
          this.bootstrapRegistryInitializers = new ArrayList<>(getSpringFactoriesInstances(BootstrapRegistryInitializer.class));
          // 獲取 容器初始化器:在 run 方法中的 prepareContext( ... ); 里會被使用
          setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class));
          // 獲取 監聽器:在 run 方法中 listeners.xxx 時被使用
          setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
      
          this.mainApplicationClass = deduceMainApplicationClass();
      }

       

      3.run方法詳解

      public ConfigurableApplicationContext run(String... args) {
          long startTime = System.nanoTime();
          DefaultBootstrapContext bootstrapContext = createBootstrapContext();
          ConfigurableApplicationContext context = null;
          configureHeadlessProperty();
      
          // 第一步:創建監聽器
          SpringApplicationRunListeners listeners = getRunListeners(args);
      
          // 發布事件:開始啟動
          listeners.starting(bootstrapContext, this.mainApplicationClass);
      
          try {
              ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
      
              // 第二步:準備環境變量
              // 把一系列設置整合成 environment,包括 系統變量、JVM參數、啟動參數(args)、配置文件(application、bootstrap等)
              ConfigurableEnvironment environment = prepareEnvironment(listeners, bootstrapContext, applicationArguments);
      
              Banner printedBanner = printBanner(environment);
      
              // 第三步:創建空容器
              // 根據 new 時判斷的 web類型(webApplicationType),創建對應類型的容器
              context = createApplicationContext();
      
              context.setApplicationStartup(this.applicationStartup);
      
              // 第四步:準備容器
              // 把前面準備的東西注入進去,包括 環境變量(environment)、事件監聽器(listeners)、啟動參數(applicationArguments)
              prepareContext(bootstrapContext, context, environment, listeners, applicationArguments, printedBanner);
      
              // 第五步:啟用容器
              // 解析@SpringBootApplication注解,加載自動配置類
              // 進行Bean的掃描、加載、實例化、依賴注入
              // 如果是Web應用,會啟動一個內嵌式的Web服務器比如Tomcat
              refreshContext(context);
      
              // 容器初始化后的操作,是個空方法,要使用需要繼承并重寫
              afterRefresh(context, applicationArguments);
      
              Duration timeTakenToStartup = Duration.ofNanos(System.nanoTime() - startTime);
              if (this.logStartupInfo) {
                  new StartupInfoLogger(this.mainApplicationClass).logStarted(getApplicationLog(), timeTakenToStartup);
              }
      
              // 發布事件:已啟動
              listeners.started(context, timeTakenToStartup);
      
              // 執行啟動后的自定方法:
              // 實現 ApplicationRunner、CommandLineRunner 接口
              callRunners(context, applicationArguments);
          }
          catch (Throwable ex) {
              if (ex instanceof AbandonedRunException) {
                  throw ex; 
              }
              handleRunFailure(context, ex, listeners);
              throw new IllegalStateException(ex);
          }
          
          try {
              // 檢查應用是否還在運行
              if (context.isRunning()) {
                  Duration timeTakenToReady = Duration.ofNanos(System.nanoTime() - startTime);
                  // 發布事件:準備就緒
                  listeners.ready(context, timeTakenToReady);
              }
          }
          catch (Throwable ex) {
              if (ex instanceof AbandonedRunException) {
                  throw ex;
              }
              handleRunFailure(context, ex, null);
              throw new IllegalStateException(ex);
          }
          // 返回Bean容器
          return context;
      }

       

      posted @ 2024-05-31 03:16  Yfeil  閱讀(153)  評論(0)    收藏  舉報
      主站蜘蛛池模板: 五月天中文字幕mv在线| 国产一区二区高清不卡| 中文字幕 欧美日韩| 国产精品日日摸夜夜添夜夜添2021| www国产精品内射熟女| 日本久久精品一区二区三区| 草草浮力影院| 扒开粉嫩的小缝隙喷白浆视频| 日韩精品国产二区三区| 国产成人精品无码专区| 久久久久无码精品国产h动漫| 亚洲一区二区三区小蜜桃| 免费高潮了好湿h视频| 日韩一区二区三区精彩视频| 开心五月婷婷综合网站| 国产午夜精品理论大片| 久久精品国产亚洲夜色av| 一区二区福利在线视频| 东京一本一道一二三区| 国产 精品 自在 线免费| 日本道之久夂综合久久爱| 精品国产迷系列在线观看| 蕲春县| 鲁一鲁一鲁一鲁一澡| 国产精品亚洲mnbav网站| 大桥未久亚洲无av码在线| 中文字幕结果国产精品| 极品无码国模国产在线观看| 啊┅┅快┅┅用力啊岳网站| 成人精品一区日本无码网| 中文字幕亚洲精品第一页| 又色又爽又黄18禁美女裸身无遮挡| 中文字幕乱偷无码av先锋蜜桃| 久久久婷婷成人综合激情| 99国产午夜福利在线观看| 无码内射成人免费喷射| 97av| 国产精品国语对白露脸在线播放| 无码囯产精品一区二区免费| 亚洲区一区二区激情文学| 国产又黄又爽又不遮挡视频|