SpringBoot到Spring源码分析之事件监听器设计

说明:本章在之前章节《SpringBoot 启动流程源码分析》的基础上进行继续源码分析。

 

前面我们分析到SpringApplication类的run方法,这个方法主要在顶层设计上定义了SpringBoot项目的整个启动过程,同时包括了Spring容器的启动过程。本章继前面的基础上继续分析Spring事件监听器设计,了解Spring的事件监听器设计可以帮助我们提升程序代码的设计能力,以及为后续源码分析添加更多的基础线索

getRunListeners(args)源码分析:

public ConfigurableApplicationContext run(String... args) {


 ...省略其它


    //从缓存的META-INF/spring.factories Map中获取
   //SpringApplicationRunListeners接口的所有子类
   SpringApplicationRunListeners listeners = getRunListeners(args);
   //回调通知应用开始启动事件监听器
   listeners.starting();
   try {


     
     ...省略其它
}

getRunListeners(args);获取程序运行过程监听器的源码在前面《SpringBootSpring源码分析之META-INF/spring.factories解析过程》文章我们已经分析过,主要逻辑就是通过读取classpath下的所有META-INF/spring.factories文件,从中获取 到所有SpringApplicationRunListener接口的实现类,并进行实例化后封装到SpringApplicationRunListeners类中,源码如下:

private SpringApplicationRunListeners getRunListeners(String[] args) {


   //SpringApplicationRunListener实现类构造器参数类型数组
   //默认实现类为EventPublishingRunListener
   Class[] types = new Class[]{SpringApplication.class, String[].class};


   //将SpringApplicationRunListener实现类封装到SpringApplicationRunListeners
   //SpringApplicationRunListeners支持通过for所有事件list批量执行功能
   return new SpringApplicationRunListeners(logger,
         getSpringFactoriesInstances(SpringApplicationRunListener.class, types, this, args));
}

listeners.starting();源码分析:

SpringApplicationRunListeners(Log log, Collection listeners) {
   this.log = log;
   this.listeners = new ArrayList<>(listeners);
}


void starting() {
//可以看到前面讲的通过for批量执行事件监听器
//通过名称复数形象很好理解这个类的意义
//SpringBoot默认开始启动事件只有一个类:EventPublishingRunListener
  //这里调的正是EventPublishingRunListener类的starting方法
   for (SpringApplicationRunListener listener : this.listeners) {
      listener.starting();
   }
}

通过断点我们确定SpringBoot默认的SpringApplicationRunListener接口的实现类只有EventPublishingRunListener,在没有自定义配置情况下for循环只有一个元素便是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) {


      //前面传入的SpringApplication对象
      this.application = application;
      //启动应用类main方法参数
      this.args = args;
      //固定new SimpleApplicationEventMulticaster
      this.initialMulticaster = new SimpleApplicationEventMulticaster();
      //application.getListeners()是前面new SpringApplication对象时从
      //META-INF/spring.factories文件获取的所有ApplicationListener接口实现类配置
      for (ApplicationListener listener : application.getListeners()) {


         //将listener添加到initialMulticaster内部类ListenerRetriever
         //的Set> applicationListeners属性中
//applicationListeners这个属性后面会用到,请记住是这里初始化的
         //添加前判断是否存在AOP代理对象,如果存在则删除代理读写,重新将原listener对象添加进去
         //防止由于AOP代理问题导致同一个listener被调用两次
//注意这里将所有的监听器保存进去,根据泛型参数进行过滤不同阶段的事件
         this.initialMulticaster.addApplicationListener(listener);
      }
   }


   //回调通知应用程序开始启动事件监听器
   @Override
   public void starting() {
      this.initialMulticaster.multicastEvent(new ApplicationStartingEvent(this.application, this.args));
   }


   //回调通知Environment准备完成事件监听器
   @Override
   public void environmentPrepared(ConfigurableEnvironment environment) {
      this.initialMulticaster
            .multicastEvent(new ApplicationEnvironmentPreparedEvent(this.application, this.args, environment));
   }


   //回调通知ApplicationContext基本准备完成事件监听器
   @Override
   public void contextPrepared(ConfigurableApplicationContext context) {
      this.initialMulticaster
            .multicastEvent(new ApplicationContextInitializedEvent(this.application, this.args, context));
   }


   //回调通知ApplicationContext基本完成加载事件监听器
   @Override
   public void contextLoaded(ConfigurableApplicationContext context) {
      for (ApplicationListener listener : this.application.getListeners()) {
         if (listener instanceof ApplicationContextAware) {
            ((ApplicationContextAware) listener).setApplicationContext(context);
         }
         context.addApplicationListener(listener);
      }
      this.initialMulticaster.multicastEvent(new ApplicationPreparedEvent(this.application, this.args, context));
   }


   //回调通知基本启动完成事件监听器
   @Override
   public void started(ConfigurableApplicationContext context) {
      context.publishEvent(new ApplicationStartedEvent(this.application, this.args, context));
   }


   //回调通知成功运行起来事件监听器
   @Override
   public void running(ConfigurableApplicationContext context) {
      context.publishEvent(new ApplicationReadyEvent(this.application, this.args, context));
   }


   //回调通知启动失败事件监听器
   @Override
   public void failed(ConfigurableApplicationContext context, Throwable exception) {
      ApplicationFailedEvent event = new ApplicationFailedEvent(this.application, this.args, context, exception);
      if (context != null && context.isActive()) {
         // Listeners have been registered to the application context so we should
         // use it at this point if we can
         context.publishEvent(event);
      }
      else {
         // An inactive context may not have a multicaster so we use our multicaster to
         // call all of the context's listeners instead
         if (context instanceof AbstractApplicationContext) {
            for (ApplicationListener listener : ((AbstractApplicationContext) context)
                  .getApplicationListeners()) {
               this.initialMulticaster.addApplicationListener(listener);
            }
         }
         this.initialMulticaster.setErrorHandler(new LoggingErrorHandler());
         this.initialMulticaster.multicastEvent(event);
      }
   }


   private static class LoggingErrorHandler implements ErrorHandler {


      private static final Log logger = LogFactory.getLog(EventPublishingRunListener.class);


      @Override
      public void handleError(Throwable throwable) {
         logger.warn("Error calling ApplicationEventListener", throwable);
      }


   }


   @Override
   public int getOrder() {
      return 0;
   }


}

EventPublishingRunListener类接口SpringApplicationRunListener定义如下:

public interface SpringApplicationRunListener {
   
   //这里为了简化,删除了源码的所有注释
   default void starting() {
   }
   
   default void environmentPrepared(ConfigurableEnvironment environment) {
   }
   
   default void contextPrepared(ConfigurableApplicationContext context) {
   }
   
   default void contextLoaded(ConfigurableApplicationContext context) {
   }
   
   default void started(ConfigurableApplicationContext context) {
   }
   
   default void running(ConfigurableApplicationContext context) {
   }
   
   default void failed(ConfigurableApplicationContext context, Throwable exception) {
   }


}

除此之外,EventPublishingRunListener类还实现了Spring排序标示符接口Ordered,可以通过Spring封装的规则进行排序,这样可以保证多个相同的事件监听器按照我们指定的顺序去执行,Spring真可谓是良苦用心啊。这也就是为什么Spring经历十几载依然经久不衰的原因之一吧。

 

EventPublishingRunListener类实际上算是个代理包装类,它控制了每个阶段的事件类,后面通过事件类和接口实现类的泛型参数是否匹配来检索对应的事件监听器。由于EventPublishingRunListener类不同阶段的事件监听实现类似,下面只分析其中starting事件源码。

starting事件方法源码分析:

//回调通知应用程序开始启动事件监听器
@Override
public void starting() {
   //application为SpringApplicatin对象
   //args为启动应用类main方法参数
   //构造参数时固定new SimpleApplicationEventMulticaster
   this.initialMulticaster.multicastEvent(new ApplicationStartingEvent(this.application, this.args));
}


@Override
public void multicastEvent(ApplicationEvent event) {


   //resolveDefaultEventType方法逻辑是将事件类型包装为泛型工具类
   //方便后面根据对应阶段事件接口的泛型参数匹配进行过滤掉其它的事件监听器
   multicastEvent(event, resolveDefaultEventType(event));
}




private ResolvableType resolveDefaultEventType(ApplicationEvent event) {
   //封装为ResolvableType,提供Java泛型更方便的操作API
   return ResolvableType.forInstance(event);
}




@Override
public void multicastEvent(final ApplicationEvent event, @Nullable ResolvableType eventType) {
   ResolvableType type = (eventType != null ? eventType : resolveDefaultEventType(event));




   //前面new SimpleApplicationEventMulticaster对象时,
   //通过调用addApplicationListener方法将从META-INF/spring.factories文件获取的
   //所有ApplicationListener接口实现类保存到SimpleApplicationEventMulticaster对象的
   //内部类ListenerRetriever defaultRetriever的applicationListeners Set属性中
   //实际上是从SpringApplication对象中拿到的,前面实例化SpringApplication对象时读取META-INF/spring.factories文件的
   //getApplicationListeners(event, type)方法逻辑是从applicationListeners Set属性中检索到
   //对应event类型的事件对象,并将结果缓存在Map retrieverCache
   for (final ApplicationListener listener : getApplicationListeners(event, type)) {
      Executor executor = getTaskExecutor();
      //如果实例化时设置了线程池,则通过线程是异步执行
      if (executor != null) {
         executor.execute(() -> invokeListener(listener, event));
      } else {


         //否则同步执行,默认实例化时没有设置线程池,所以走这里
         invokeListener(listener, event);
      }
   }
}




protected void invokeListener(ApplicationListener listener, ApplicationEvent event) {
   ErrorHandler errorHandler = getErrorHandler();
   if (errorHandler != null) {
      try {
         doInvokeListener(listener, event);
      } catch (Throwable err) {
         errorHandler.handleError(err);
      }
   } else {


      //实例化时没有设置错误处理器,走这里
      doInvokeListener(listener, event);
   }
}


@SuppressWarnings({"rawtypes", "unchecked"})
private void doInvokeListener(ApplicationListener listener, ApplicationEvent event) {
   try {


      //千山水远,终于走到调用实际的事件通知方法,这里调用的便是子类实现的逻辑
      listener.onApplicationEvent(event);
   } catch (ClassCastException ex) {
      String msg = ex.getMessage();
      if (msg == null || matchesClassCastMessage(msg, event.getClass())) {
         // Possibly a lambda-defined listener which we could not resolve the generic event type for
         // -> let's suppress the exception and just log a debug message.
         Log logger = LogFactory.getLog(getClass());
         if (logger.isDebugEnabled()) {
            logger.debug("Non-matching event type for listener: " + listener, ex);
         }
      } else {
         throw ex;
      }
   }
}


getApplicationListeners(event, type)方法源码分析:

protected Collection> getApplicationListeners(
      ApplicationEvent event, ResolvableType eventType) {


   //org.springframework.boot.SpringApplication 对象
   Object source = event.getSource();
   //org.springframework.boot.SpringApplication Class对象
   Class sourceType = (source != null ? source.getClass() : null);
   //Map的key,ListenerCacheKey重写了equals和hashCode方法
   ListenerCacheKey cacheKey = new ListenerCacheKey(eventType, sourceType);


   //检查缓存中是否存在,如果for第一次,这里是空的
   ListenerRetriever retriever = this.retrieverCache.get(cacheKey);
   if (retriever != null) {
      //for非第一次则返回缓存数据
      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();
         }
         //实例化ListenerRetriever
         retriever = new ListenerRetriever(true);


         //retrieveApplicationListeners方法核心逻辑是从applicationListeners Set属性中检索到
         //对应event类型的事件对象,并将结果缓存在Map retrieverCache
         Collection> 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 final ListenerRetriever defaultRetriever = new ListenerRetriever(false);


private Collection> retrieveApplicationListeners(
      ResolvableType eventType, @Nullable Class sourceType, @Nullable ListenerRetriever retriever) {


   List> allListeners = new ArrayList<>();
   Set> listeners;
   Set listenerBeans;
   synchronized (this.retrievalMutex) {
      //public final Set> applicationListeners = new LinkedHashSet<>();
      //调用addApplicationListener方法从SpringApplication对象拿到的所有
      //配置在META-INF/spring.factories文件的ApplicationListener子类
      listeners = new LinkedHashSet<>(this.defaultRetriever.applicationListeners);
      listenerBeans = new LinkedHashSet<>(this.defaultRetriever.applicationListenerBeans);
   }
   for (ApplicationListener listener : listeners) {
      //通过判断事件监听器实现类的泛型参数是否匹配当前通知事件的事件对象进行检索
      if (supportsEvent(listener, eventType, sourceType)) {
         if (retriever != null) {
            //将匹配的添加到缓存
            retriever.applicationListeners.add(listener);
         }
         allListeners.add(listener);
      }
   }
   
   //这里是其它情况分支的逻辑,实现思路差不多,这里改为从BeanFactory获取事件监听器对象
   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);
               if (!allListeners.contains(listener) && supportsEvent(listener, eventType, sourceType)) {
                  if (retriever != null) {
                     if (beanFactory.isSingleton(listenerBeanName)) {
                        retriever.applicationListeners.add(listener);
                     }
                     else {
                        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);
   
   //更新applicationListeners集合
   if (retriever != null && retriever.applicationListenerBeans.isEmpty()) {
      retriever.applicationListeners.clear();
      retriever.applicationListeners.addAll(allListeners);
   }
   //返回
   return allListeners;
}


总结:

  在分析框架源码过程中除了要了解源码逻辑外,更多地还要去思考为什么这么设计,如果让自己去写有没有更好的实现方式,这样才能使自己在源码中获取到更多的提升和进步。例如前面的根据是否传入线程池来决定是否异步执行设计、根据泛型参数来检索事件监听器、必要的Map缓存、线程安全的双重判断、顶层接口以及入参的设计、回调通知设计、各种工具类封装以及各种逻辑严谨性验证等思想都是值得我们去借鉴和思考的。

欢迎扫码下面二维码关注我

Java软件编程之家

你可能感兴趣的:(SpringBoot到Spring源码分析之事件监听器设计)