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

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

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

      Loading

      Spring-Cloud-Context模塊

      簡介

      SpringCloud這個框架本身是建立在SpringBoot基礎之上的,所以使用SpringCloud的方式與SpringBoot相仿。也是通過類似如下代碼進行啟動。

      SpringApplication.run(XxxApplication.class, args);

      其中 XxxApplication.class 類上也需要添加 @SpringBootApplication注解。
      要使用SpringCloud框架,在pom文件中要確保引入 spring-cloud-starter 依賴包,spring-cloud-starter依賴如下的jar:

      <dependencies>
          <dependency>
              <groupId>org.springframework.boot</groupId>
              <artifactId>spring-boot-starter</artifactId>
          </dependency>
          <dependency>
              <groupId>org.springframework.cloud</groupId>
              <artifactId>spring-cloud-context</artifactId>
          </dependency>
          <dependency>
              <groupId>org.springframework.cloud</groupId>
              <artifactId>spring-cloud-commons</artifactId>
          </dependency>
      </dependencies>
      

      其中 spring-cloud-context-x.y.z.RELEASE.jarspring-cloud-commons-x.y.z.RELEASE.jar 下的 META-INF 目錄下都包含 spring.factories 文件,所以可以把這兩個jar看作是springCloud程序的入口

      SpringCloud在構建上下文<即ApplicationContext實例>時,采用了Spring父子容器的設計,會在 SpringBoot構建的容器<后面稱之為應用容器>之上創建一一父容器Bootstrap Application Context .

      那么SpringCloud設計出Bootstrap Application Context ,并把它作為應用容器的父容器的目的是什么呢?

      因為SpringCloud 作為一個分布式微服務框架,需要使用全局的配置中心,而配置中心的配置是可以提供給應用容器的,所以在應用容器初始化和實例化Bean之前需要先完成配置中心的實例化,這個任務就由Bootstrap Application Context 來完成,而配置中心的相關配置屬性就從 bootstrap.propertiesbootstrap.yml 文件中讀取。

      但要注意的是,在Bootstrap Application Context 啟動工作完成之后,其從bootstrap.properties或bootstrap.yml文件中讀取的配置,是會被應用容器對應的application.properties或yml文件中的同名屬性覆蓋的。

      從源碼角度分析上面的論述

      1.代碼運行時還是從SpringApplication實例的run方法開始 ,此處會觸發 BootstrapApplicationListener 類中的代碼 , Bootstrap Application Context 的創建就是通過這個監聽器觸發的

      public ConfigurableApplicationContext run(String... args) {
          StopWatch stopWatch = new StopWatch();
          stopWatch.start();
          ConfigurableApplicationContext context = null;
          Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList<>();
          configureHeadlessProperty();
          // 此處會加載spring-cloud-context提供的監聽器org.springframework.cloud.bootstrap.BootstrapApplicationListener.class
          SpringApplicationRunListeners listeners = getRunListeners(args);
          listeners.starting();
          try {
              ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);            
              // 此處會發布ApplicationEnvironmentPreparedEvent事件,觸發BootstrapApplicationListener中的代碼
              ConfigurableEnvironment environment = prepareEnvironment(listeners, applicationArguments);
              configureIgnoreBeanInfo(environment);
              Banner printedBanner = printBanner(environment);
              context = createApplicationContext();
              exceptionReporters = getSpringFactoriesInstances(
                  SpringBootExceptionReporter.class,
                  new Class[] { ConfigurableApplicationContext.class }, context);
              prepareContext(context, environment, listeners, applicationArguments,
                             printedBanner);
              refreshContext(context);
              afterRefresh(context, applicationArguments);
              stopWatch.stop();
              if (this.logStartupInfo) {
                  new StartupInfoLogger(this.mainApplicationClass)
                      .logStarted(getApplicationLog(), stopWatch);
              }
              listeners.started(context);
              callRunners(context, applicationArguments);
          }
          catch (Throwable ex) {
              handleRunFailure(context, ex, exceptionReporters, listeners);
              throw new IllegalStateException(ex);
          }
      
          try {
              listeners.running(context);
          }
          catch (Throwable ex) {
              handleRunFailure(context, ex, exceptionReporters, null);
              throw new IllegalStateException(ex);
          }
          return context;
      }
      

      2.Bootstrap Application Context 的實例化 ,由BootstrapApplicationListener類的 onApplicationEvent方法觸發

      public void onApplicationEvent(ApplicationEnvironmentPreparedEvent event) {
          ConfigurableEnvironment environment = event.getEnvironment();        
          // 可以通過環境變量 spring.cloud.bootstrap.enabled來禁止使用Bootstrap容器
          if (!environment.getProperty("spring.cloud.bootstrap.enabled", Boolean.class, true)) {
              return;
          }
          // 由于Bootstrap容器在創建時還是會再次調用上面步驟1的代碼,還會再次觸發
          // BootstrapApplicationListener類這個方法,所以此處作個判斷,
          // 如果當前是Bootstrap容器的處理,則直接返回
          if (environment.getPropertySources().contains(BOOTSTRAP_PROPERTY_SOURCE_NAME)) {
              return;
          }
          ConfigurableApplicationContext context = null;        
          // 獲取配置文件的名字,默認為bootstrap.properties或.yml ,并且這個名字可以通過 spring.cloud.bootstrap.name在環境中配置
          String configName = environment.resolvePlaceholders("${spring.cloud.bootstrap.name:bootstrap}");
          for (ApplicationContextInitializer<?> initializer : event.getSpringApplication()
               .getInitializers()) {             
              // 從相應jar中的spring.factories文件中讀取初始化器的配置類實例,如果這個實例類是
              // ParentContextApplicationContextInitializer類型,則直接從該類中獲取到父容器
              // 默認情況下,沒有提供這樣的類,下面這段代碼會跳過
              if (initializer instanceof ParentContextApplicationContextInitializer) {
                  context = findBootstrapContext(
                      (ParentContextApplicationContextInitializer) initializer,
                      configName);
              }
          }
          if (context == null) {            // 此處分析見步驟3
              context = bootstrapServiceContext(environment, event.getSpringApplication(), configName);
              event.getSpringApplication().addListeners(new CloseContextOnFailureApplicationListener(context));
          }
      
          apply(context, event.getSpringApplication(), environment);
      }
      

      3.bootstrap容器的創建

      private ConfigurableApplicationContext bootstrapServiceContext(
          ConfigurableEnvironment environment, final SpringApplication application,
          String configName) {
          /**此處代碼主要是從各處獲取屬性配置,此處忽略**/
          // TODO: is it possible or sensible to share a ResourceLoader?
          SpringApplicationBuilder builder = new SpringApplicationBuilder()
              .profiles(environment.getActiveProfiles()).bannerMode(Mode.OFF)
              .environment(bootstrapEnvironment)
              // Don't use the default properties in this builder
              .registerShutdownHook(false).logStartupInfo(false)
              .web(WebApplicationType.NONE);        
          // SpringApplicationBuilder的作用:1.構建SpringApplication  2.構建ApplicationContext        
          // 這里需要思考一下,SpringBoot在啟動時已經構建了一個SpringApplication實例,為何此處又構建了一個         
          // 這是因為這個SpringApplication實例的構建環境和SringBoot原生構建的那個不同,看一下上一行代碼就能明白
          final SpringApplication builderApplication = builder.application();
          if(builderApplication.getMainApplicationClass() == null){
              builder.main(application.getMainApplicationClass());
          }
          if (environment.getPropertySources().contains("refreshArgs")) {
              builderApplication.setListeners(filterListeners(builderApplication.getListeners()));
          }        
          // 從springFactories文件中查找BootstrapConfiguration的配置類
          builder.sources(BootstrapImportSelectorConfiguration.class);        
          // 構建出BootstrapContext
          final ConfigurableApplicationContext context = builder.run();        
          context.setId("bootstrap");
          // 設置BootstrapContext成為應用Context的父容器,此處分析見步驟4
          addAncestorInitializer(application, context);
          // It only has properties in it now that we don't want in the parent so remove
          // it (and it will be added back later)
          bootstrapProperties.remove(BOOTSTRAP_PROPERTY_SOURCE_NAME);
          mergeDefaultProperties(environment.getPropertySources(), bootstrapProperties);
          return context;
      }
      

      4.設置BootstrapContext成為應用Context的父容器 (在SpringApplication實例中動態添加了一個初始化器,相當于給應用Context埋了個雷)

      private void addAncestorInitializer(SpringApplication application, ConfigurableApplicationContext context) {
          boolean installed = false;        
          // 從spring.factories文件中獲取初始化器的配置類且類型為AncestorInitializer
          for (ApplicationContextInitializer<?> initializer : application.getInitializers()) {
              if (initializer instanceof AncestorInitializer) {
                  installed = true;
                  // New parent
                  ((AncestorInitializer) initializer).setParent(context);
              }
          }        
          // 默認情況下是沒有配圍置AncestorInitializer這樣的類,此處是則執行由BootstrapListener提供的內部類
          if (!installed) {            
              // 將BootstrapContext作為父容器傳到AncestorInitializer實例中,并將其放入SpringApplication實例的初始器列表中
              application.addInitializers(new AncestorInitializer(context));
          }
      }
      

      5.初始化器AncestorInitializer被觸發,是由應用Context的處理觸發的

      public void initialize(ConfigurableApplicationContext context) {  
          // 這個context是應用Context
          while (context.getParent() != null && context.getParent() != context) {
              context = (ConfigurableApplicationContext) context.getParent();
          }
          reorderSources(context.getEnvironment());            
          // 完成應用容器的父容器的設置
          new ParentContextApplicationContextInitializer(this.parent)
              .initialize(context);
      }
      

      6.ParentContextApplicationContextInitializer代碼

      private static class ParentContextApplicationContextInitializer
          implements ApplicationContextInitializer<ConfigurableApplicationContext> {
          private final ApplicationContext parent;
      
          ParentContextApplicationContextInitializer(ApplicationContext parent) {
              this.parent = parent;
          }
      
          @Override
          public void initialize(ConfigurableApplicationContext applicationContext) {
              // 設置應用Context的父容器
              applicationContext.setParent(this.parent);
          }
      
      }
      

      總結

      1. SpringCloud Context模塊的功能:主要是構建了一個Bootstrap容器,并讓其成為原有的SpringBoot程序構建的容器的父容器。
      2. Bootstrap容器的作用:是為了預先完成一些Bean的實例化工作,可以把Bootstrap容器看作是先頭部隊。
      3. Bootstrap容器的構建:是利用了SpringBoot的事件機制,當SpringBoot的初始化Environment準備好之后會發布一個事件,這個事件的監聽器將負責完成Bootstrap容器的創建。構建時是使用SpringApplicationBuilder類來完成的。
      4. 如何讓Bootstrap容器與應用Context 建立父子關系:由于Bootstrap容器與應用Context都是關聯著同一個SpringApplication實例,Bootstrap容器自己完成初始化器的調用之后,會動態添加了一個初始化器 AncestorInitializer,相當于給應用Context埋了個雷,這個初始化器在應用容器進行初始化器調用執行時,完成父子關系的設置。

      擴展

      1. spring-cloud-context源碼解讀

      原文鏈接 http://www.rzrgm.cn/hzhuxin/p/10496762.html

      posted @ 2021-11-25 21:28  dai.sp  閱讀(1525)  評論(0)    收藏  舉報
      主站蜘蛛池模板: 中国丰满少妇人妻xxx性董鑫洁| 亚洲乱理伦片在线观看中字| 国产精品午夜福利免费看 | 青青草原国产精品啪啪视频| 亚洲欧美综合人成在线| 国产偷拍自拍视频在线观看| 一本精品99久久精品77| 国产精品午夜福利视频234区| 爱性久久久久久久久| 视频一区视频二区亚洲视频| 高清dvd碟片 生活片| 99久热在线精品视频| 韩国福利片在线观看播放| 中文字幕在线视频不卡| 亚洲嫩模喷白浆在线观看| caoporn免费视频公开| 精品午夜福利在线观看| 里番全彩爆乳女教师| 97精品亚成在人线免视频| 福利视频在线一区二区| 亚洲精品熟女国产| 狼色精品人妻在线视频| 极品尤物被啪到呻吟喷水| 丝袜人妻一区二区三区网站| 国产精品自偷一区在线观看| 美女无遮挡免费视频网站| 亚洲性猛交xxxx| 国内自拍第一区二区三区| 国产不卡精品视频男人的天堂 | 中文字幕日本一区二区在线观看 | 青青草无码免费一二三区| 松溪县| 中文字幕亚洲精品第一页| 中文字幕亚洲国产精品| 依依成人精品视频在线观看| 在线看片免费人成视久网| 东方四虎av在线观看| 亚洲三区在线观看无套内射| 无码人妻斩一区二区三区| 中文字幕在线精品国产| 泾阳县|