中文字幕第五页-中文字幕第页-中文字幕韩国-中文字幕最新-国产尤物二区三区在线观看-国产尤物福利视频一区二区

springboot2.0.6如何啟動監聽器

這篇文章給大家介紹springboot2.0.6如何啟動監聽器,內容非常詳細,感興趣的小伙伴們可以參考借鑒,希望對大家能有所幫助。

創新互聯建站堅持“要么做到,要么別承諾”的工作理念,服務領域包括:成都做網站、網站制作、企業官網、英文網站、手機端網站、網站推廣等服務,滿足客戶于互聯網時代的楚雄州網站設計、移動媒體設計的需求,幫助企業找到有效的互聯網解決方案。努力成為您成熟可靠的網絡建設合作伙伴!

解析SpringApplication的run方法解析

public ConfigurableApplicationContext run(String... args) {
   ......//省略
    // 獲取一個run監聽器,主要監聽SpringApplication對象,(內部只有一個EventPublishingRunListener)
   SpringApplicationRunListeners listeners = getRunListeners(args);
    //調用監聽器的啟動,當SpringApplication對象的run方法剛啟動的時候(依靠SimpleApplicationEventMulticaster)
   listeners.starting();
   ......//省略
}

1. SpringApplicationRunListeners

    SpringApplicationRunListeners 是一個集合類,內部包含一個 log 和包含 SpringApplicationRunListener 的 List。而 SpringApplicationRunListener 主要是監聽 SpringApplication 對象的,里面的方法都定義了在何時調用 SpringApplicationRunListener 的各種方法。

    下面的每一個方法 SpringApplicationRunListener 都把其包裝成一個事件,在spring容器還未成功 refreshed 之前都是使用SimpleApplicationEventMulticaster 去尋找對該事件感興趣的ApplicationListener,然后調用其onApplicationEvent方法

  1. starting:當SpringApplication對象的run方法剛啟動的時候(依靠SimpleApplicationEventMulticaster)

  2. environmentPrepared:在environment Prepared 但是spring容器還未創建的時候(依靠SimpleApplicationEventMulticaster)

  3. contextPrepared:當spring容器已經創建且準備好了,(目前是空的實現)

  4. contextLoaded:當spring容器已經loaded 且未refresh 。load就是將我們的primaryClass注冊到spring容器中,(依靠SimpleApplicationEventMulticaster) 同時將之前獲取到的ApplicationListener都加入到spring容器中,此時如果ApplicationListener還是ApplicationContextAware的也要調用其setApplicationContext方法。

  5. started:spring容器已經刷新過且應用已經啟動,但是CommandLineRunners和ApplicationRunners還未調用,直接通過spring容器自己發送(因為ApplicationListener已經加入spring容器)

  6. running:我們已經調用了CommandLineRunners,直接通過spring容器自己發送(因為ApplicationListener已經加入spring容器)

  7. failed:當異常發生的時候就調用這個,如果spring容器沒有loaded 或者沒有激活就使用SimpleApplicationEventMulticaster,否則還是依靠spring容器自己

2. 獲取SpringApplicationRunListeners實例源碼分析

1. getRunListeners

public class SpringApplication {
    // 獲取監聽
   private SpringApplicationRunListeners getRunListeners(String[] args) {
        // 定義class數組
      Class<?>[] types = new Class<?>[] { SpringApplication.class, String[].class };
        // 創建SpringApplicationRunListeners對象
      return new SpringApplicationRunListeners(logger, getSpringFactoriesInstances(
            SpringApplicationRunListener.class, types, this, args));
   }
}

默認情況下,getRunListeners 方法從 spring.factories 文件中找出key為 SpringApplicationRunListener 的類有:

    org.springframework.boot.context.event.EventPublishingRunListener

這里我們看到了一個熟悉的方法getSpringFactoriesInstances(SpringApplicationRunListener.class, types, this, args),前面的博文我們已經詳細介紹過該方法是怎么一步步的獲取到META-INF/spring.factories中的指定的key的value,獲取到以后怎么實例化類的(參考)。執行 獲取的值如下圖

springboot2.0.6如何啟動監聽器

    從上圖debug結果,我們可以看到我們獲取到了一個監聽器EventPublishingRunListener,該監聽器是Spring容器的啟動監聽器。listeners.starting()方法開啟了監聽事件

2. SpringApplicationRunListener的實現類EventPublishingRunListener

public class EventPublishingRunListener implements SpringApplicationRunListener, Ordered {
   private final SpringApplication application;
   private final String[] args;
   private final SimpleApplicationEventMulticaster initialMulticaster;
    // 加載監聽器類
   public EventPublishingRunListener(SpringApplication application, String[] args) {
      this.application = application;
      this.args = args;
      this.initialMulticaster = new SimpleApplicationEventMulticaster();
        // 給initialMulticaster 添加listener
      for (ApplicationListener<?> listener : application.getListeners()) {
         this.initialMulticaster.addApplicationListener(listener);
      }
   }
   // 實現類調用EventPublishingRunListener的方法
   public void starting() {
       this.initialMulticaster.multicastEvent(
           // 創建了一個ApplicationStartingEvent事件,將springapplication的this.application傳入,因此監聽的時候獲取的是SpringApplication實例
         new ApplicationStartingEvent(this.application, this.args));
   }
    ......//省略
}

    EventPublishingRunListener的初始化方法中 對application、args進行了賦值,并對SimpleApplicationEventMulticaster進行了初始化,然后獲取application中的監聽器添加給SimpleApplicationEventMulticaster對象。

進入SimpleApplicationEventMulticaster類的初始化方法,如下

public class SimpleApplicationEventMulticaster extends AbstractApplicationEventMulticaster {
   private Executor taskExecutor;
   private ErrorHandler errorHandler;
   public void multicastEvent(ApplicationEvent event) {
      multicastEvent(event, resolveDefaultEventType(event));
   }
   public void multicastEvent(final ApplicationEvent event, @Nullable ResolvableType eventType) {
      ResolvableType type = (eventType != null ? eventType : resolveDefaultEventType(event));
        // 注意getApplicationListeners獲取對應的事件監聽器
      for (final ApplicationListener<?> listener : getApplicationListeners(event, type)) {
         Executor executor = getTaskExecutor();
         if (executor != null) {
            executor.execute(() -> invokeListener(listener, event));
         }
         else {
            invokeListener(listener, event);
         }
      }
   }
}

SimpleApplicationEventMulticaster類繼承 AbstractApplicationEventMulticaster

public abstract class AbstractApplicationEventMulticaster
      implements ApplicationEventMulticaster, BeanClassLoaderAware, BeanFactoryAware {
   protected Collection<ApplicationListener<?>> getApplicationListeners(
         ApplicationEvent event, ResolvableType eventType) {
      Object source = event.getSource();
      Class<?> sourceType = (source != null ? source.getClass() : null);
      ListenerCacheKey cacheKey = new ListenerCacheKey(eventType, sourceType);
      // Quick check for existing entry on ConcurrentHashMap…
       // 快速檢測 COncurrentHashMap 的現有條目
      ListenerRetriever retriever = this.retrieverCache.get(cacheKey);
      if (retriever != null) {
         return retriever.getApplicationListeners();
      }
      if (this.beanClassLoader == null ||
            (ClassUtils.isCacheSafe(event.getClass(), this.beanClassLoader) &&
                  (sourceType == null || ClassUtils.isCacheSafe(sourceType, this.beanClassLoader)))) {
         // Fully synchronized building and caching of a ListenerRetriever
         synchronized (this.retrievalMutex) {
            retriever = this.retrieverCache.get(cacheKey);
            if (retriever != null) {
               return retriever.getApplicationListeners();
            }
            retriever = new ListenerRetriever(true);
            Collection<ApplicationListener<?>> listeners =
                  retrieveApplicationListeners(eventType, sourceType, retriever);
            this.retrieverCache.put(cacheKey, retriever);
            return listeners;
         }
      }
      else {
         // No ListenerRetriever caching -> no synchronization necessary
         return retrieveApplicationListeners(eventType, sourceType, null);
      }
   }
    // 實際上檢索給定事件和源類型的應用程序監聽器是否匹配
   private Collection<ApplicationListener<?>> retrieveApplicationListeners(
         ResolvableType eventType, @Nullable Class<?> sourceType, @Nullable ListenerRetriever retriever) {
      List<ApplicationListener<?>> allListeners = new ArrayList<>();
      Set<ApplicationListener<?>> listeners;
      Set<String> listenerBeans;
      synchronized (this.retrievalMutex) {
            // 這個listener集合就是前文提到的從配置中過濾的10個監聽器(圖1)
         listeners = new LinkedHashSet<>(this.defaultRetriever.applicationListeners);
         listenerBeans = new LinkedHashSet<>(this.defaultRetriever.applicationListenerBeans);
      }
       // 循環10個listener調用supportsEvent方法
      for (ApplicationListener<?> listener : listeners) {
         if (supportsEvent(listener, eventType, sourceType)) {
            if (retriever != null) {
               retriever.applicationListeners.add(listener);
            }
            allListeners.add(listener);
         }
      }
      ......//省略
      AnnotationAwareOrderComparator.sort(allListeners);
      if (retriever != null && retriever.applicationListenerBeans.isEmpty()) {
         retriever.applicationListeners.clear();
         retriever.applicationListeners.addAll(allListeners);
      }
      return allListeners;
   }
   protected boolean supportsEvent(
      ApplicationListener<?> listener, ResolvableType eventType, @Nullable Class<?> sourceType) {
      GenericApplicationListener smartListener = (listener instanceof GenericApplicationListener ?
         (GenericApplicationListener) listener : new GenericApplicationListenerAdapter(listener));
      return (smartListener.supportsEventType(eventType) && smartListener.supportsSourceType(sourceType));
   }
}

3. 監聽過程

    -->程序啟動
    -->調用getRunListeners(args)獲取SpringApplicationRunListeners實例
        -->getSpringFactoriesInstances()獲取Spring工廠實例集合
            -->loadFactoryNames()通過classLoader加載/META-INF/spring.factories文件,獲取指定class對應的類全限定名稱集合
                -->loadSpringFactories() 通過classLoader循環加載/META-INF/spring.factories文件,獲取文件中類全限定名稱集合返回
    -->createSpringFactoriesInstances()根據加載文件返回的類全限定名稱集合創建工廠實例,反射
    -->listeners.starting()啟動監聽器
    -->multicastEvent(ApplicationEvent event)組播ApplicationEvent事件
    -->getApplicationListeners()判斷監聽器類型是否與當前監聽器類型相同
    -->retrieveApplicationListeners(eventType, sourceType, retriever)檢索給定事件和源類型的應用程序監聽器。
    -->supportsEvent(listener, eventType, sourceType)確認給定的監聽器是否支持給定的事件。
    -->GenericApplicationListenerAdapter(ApplicationListener<?> delegate)為給定的委托創建一個新的GenericApplicationListener。
    -->resolveDeclaredEventType(ApplicationListener<ApplicationEvent> listener)發布事件監聽
    -->supportsEventType(eventType)從指定類型解析事件
    -->結束

4. SpringApplicationRunListener,ApplicationListener和SimpleApplicationEventMulticaster的關系

  1. SpringApplicationRunListener的那些方法底層還是依靠spring容器去發布事件

  2. 底層還是會被ApplicationListener給監聽到

  3. 在spring容器prepareContext調用之后會將ApplicationListener都加入到SimpleApplicationEventMulticaster,在這之后所有的事件都會lazy發送,即先存在earlyApplicationEvents。等到spring容器refresh之后注冊所有ApplicationListener,然后在統一發送之前存儲的事件。

關于springboot2.0.6如何啟動監聽器就分享到這里了,希望以上內容可以對大家有一定的幫助,可以學到更多知識。如果覺得文章不錯,可以把它分享出去讓更多的人看到。

網頁名稱:springboot2.0.6如何啟動監聽器
標題URL:http://www.2m8n56k.cn/article44/ijcdhe.html

成都網站建設公司_創新互聯,為您提供自適應網站微信小程序Google軟件開發商城網站外貿建站

廣告

聲明:本網站發布的內容(圖片、視頻和文字)以用戶投稿、用戶轉載內容為主,如果涉及侵權請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網站立場,如需處理請聯系客服。電話:028-86922220;郵箱:[email protected]。內容未經允許不得轉載,或轉載時需注明來源: 創新互聯

搜索引擎優化
主站蜘蛛池模板: 欧美精品一区二区在线观看播放 | 久久se精品一区二区国产 | 操美女大逼视频 | 国产精品一区二区四区 | 伊人久热这里只有精品视频99 | 国产年成美女网站视频免费看 | 欧美成人专区 | 在线观看偷拍视频一区 | 国产一区三区二区中文在线 | 国产成人午夜性a一级毛片 国产成人午夜性视频影院 国产成人香蕉久久久久 | 欧美色老头oldvideo | 高清国产露脸捆绑01经典 | 国产精品久久久久久久久久一区 | 怡红院色视频在线 | 免费国产成人高清在线观看不卡 | 午夜欧美在线 | 国产精品无圣光一区二区 | 最新国产美女一区二区三区 | 久久视频精品线视频在线网站 | 免费国产a国产片高清 | 老司机精品福利视频 | 国产免费一级高清淫曰本片 | 97视频免费上传播放 | 91精品视品在线播放 | 全免费a级毛片免费看 | 国产一区二区高清在线 | 亚洲国产爱久久全部精品 | 中文字幕精品视频在线 | 日本免费人成黄页网观看视频 | 特级黄色毛片视频 | 一级a性色生活片久久毛片 一级a做爰片欧欧美毛片4 | 中文国产成人精品久久无广告 | 亚洲一区二区在线 | 好看欧美视频高清va | 欧美一级高清片欧美国产欧美 | 欧美日韩国产在线人成dvd | 成人爱做日本视频免费 | 一区二三区国产 | 中文字幕成人免费高清在线 | 99精品视频在线视频免费观看 | 欧美日韩在线观看区一二 |