springboot启动流程源码分析(三)getRunListeners()

springboot源码分析系列文章

springboot启动流程源码之一(new SpringApplication(primarySources))

springboot启动流程源码分析(二)run(args)

本文将主要分析getRunListeners()方法,该方法主要获取并启动监听器

在这里插入图片描述
该类中有一个方法 getSpringFactoriesInstances()是不是很熟悉,在源码分析(一)中对此方法进行了解读,主要是用来获取指定类型的实例集合。

那么在这儿,SpringAoolicationRunListener主要是获取哪个实现类呢?
在这里插入图片描述
在spring.factories中可以看到,获取的是org.springframework.boot.context.event.EventPublishingRunListener类。说的再简单点,getRunListeners就是准备好了运行时监听器EventPublishingRunListener
在这里插入图片描述
在实现类EventPublishingRunListener的构造方法中,构造了一个SimpleApplicationEventMulticaster对象,并将SpringApplication的listeners中的全部listener赋值到SimpleApplicationEventMulticaster对象的属性defaultRetriever(类型是ListenerRetriever)的applicationListeners集合中。

//获取到监听器之后,启动监听器。
listeners.starting();

再来看看listeners.starting()做了什么操作。
在这里插入图片描述
构建了一个ApplicationStartingEvent事件,并将其发布出去,其中调用了resolveDefaultEventType方法,该方法返回了一个封装了事件的默认类型(ApplicationStartingEvent)的ResolvableType对象。我们接着往下看,看看这个发布过程做了些什么。
在这里插入图片描述
遍历getApplicationListeners(event, type),然后对每个listener进行invokeListener(listener, event)

①那么getApplicationListeners(event, type)是获取什么呢?

/**
   * Return a Collection of ApplicationListeners matching the given
   * event type. Non-matching listeners get excluded early.
   * @param event the event to be propagated. Allows for excluding
   * non-matching listeners early, based on cached matching information.
   * @param eventType the event type
   * @return a Collection of ApplicationListeners
   * @see org.springframework.context.ApplicationListener
   */
  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...
    ListenerRetriever retriever = this.retrieverCache.get(cacheKey);
    // 从map中获取,如果之前已经存在该key,则直接从map获取
    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);
        // map中没有该key,则先获取所有的监听器
        Collection<ApplicationListener<?>> listeners =
            retrieveApplicationListeners(eventType, sourceType, retriever);
        // 重新put到map中,下次可以直接从map中获取
                this.retrieverCache.put(cacheKey, retriever);
        return listeners;
      }
    }
    else {
      // No ListenerRetriever caching -> no synchronization necessary
      return retrieveApplicationListeners(eventType, sourceType, null);
    }
  }

跟踪retrieveApplicationListeners()方法,查看如何获取监听器列表

private Collection<ApplicationListener<?>> retrieveApplicationListeners(
      ResolvableType eventType, Class<?> sourceType, ListenerRetriever retriever) {

    LinkedList<ApplicationListener<?>> allListeners = new LinkedList<ApplicationListener<?>>();
    Set<ApplicationListener<?>> listeners;
    Set<String> listenerBeans;
    synchronized (this.retrievalMutex) {
      // 1.从defaultReviewer中获取监听器列表
      listeners = new LinkedHashSet<ApplicationListener<?>>(this.defaultRetriever.applicationListeners);
      listenerBeans = new LinkedHashSet<String>(this.defaultRetriever.applicationListenerBeans);
    }
    for (ApplicationListener<?> listener : listeners) {
      // 2.针对于该Event事件的监听器,放入allListeners
      if (supportsEvent(listener, eventType, sourceType)) {
        if (retriever != null) {
          retriever.applicationListeners.add(listener);
        }
        allListeners.add(listener);
      }
    }
    if (!listenerBeans.isEmpty()) {
      BeanFactory beanFactory = getBeanFactory();
      for (String listenerBeanName : listenerBeans) {
        try {
          Class<?> listenerType = beanFactory.getType(listenerBeanName);
          if (listenerType == null || supportsEvent(listenerType, eventType)) {
            ApplicationListener<?> listener =
                beanFactory.getBean(listenerBeanName, ApplicationListener.class);
            // 针对于该Event事件的监听器,并且不存在于allListeners中的,则放入allListeners
            if (!allListeners.contains(listener) && supportsEvent(listener, eventType, sourceType)) {
              if (retriever != null) {
                retriever.applicationListenerBeans.add(listenerBeanName);
              }
              allListeners.add(listener);
            }
          }
        }
        catch (NoSuchBeanDefinitionException ex) {
          // Singleton listener instance (without backing bean definition) disappeared -
          // probably in the middle of the destruction phase
        }
      }
    }
    AnnotationAwareOrderComparator.sort(allListeners);
    return allListeners;
  }

通过以上代码可确定,监听器列表是从defaultRetriever中获取的

invokeListener()方法做了什么

其注释:使用给定的事件调用给定的监听器getApplicationListeners方法过滤出的监听器都会被调用,过滤出来的监听器包括LoggingApplicationListener,
BackgroundPreinitializer,
DelegatingApplicationListener,
LiquibaseServiceLocatorApplicationListener,
EnableEncryptablePropertiesBeanFactoryPostProcessor
五种类型的对象。这五个对象的onApplicationEvent都会被调用。那么这五个监听器的onApplicationEvent都做了些什么了,

LoggingApplicationListener:检测正在使用的日志系统,默认是logback,支持3种,优先级从高到低:logback > log4j > javalog。此时日志系统还没有初始化
BackgroundPreinitializer:另起一个线程实例化Initializer并调用其run方法,包括验证器、消息转换器等等
DelegatingApplicationListener:此时什么也没做
LiquibaseServiceLocatorApplicationListener:此时什么也没做
EnableEncryptablePropertiesBeanFactoryPostProcessor:此时仅仅打印了一句日志,其他什么也没做

关注公众号
在这里插入图片描述
每周会更新干货知识

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值