spring源码学习笔记之监听器初始化(八)

593 阅读4分钟

接下来看一下 initApplicationEventMulticaster 方法。

// 初始化事件监听多路广播器
initApplicationEventMulticaster();

监听器运用的其实就是观察者模式,不过spring中的监听器和常规的观察者模式有些不同。我们可以先看看一个常规的观察者模式是如何实现的。 这里贴一下Java与模式一书中对观察者模式的说明:

image.png

image.png

image.png

spring中监听器是基于事件驱动的: image.png

  • 逻辑执行过程
  1. 事件源来发布不同的事件
  2. 当发布事件之后会调用多播器的方法来进行事件广播操作,由多播器去触发具体的监听器去执行操作
  3. 监听器接收到具体的事件之后,可以验证匹配是否能处理当前事件,如果可以,直接处理,如果不行,不做任何操作
  • 实际代码处理
  1. 提前准备好N多个事件
  2. 初始化多播器(创建多播器对象,此多播器对象中应该包含一个监听器的集合)
  3. 准备好一系列的监听器
  4. 向多播器中注册进去已有的监听器
  5. 准备事件发布,来通知多播器循环调用监听器进行相关的逻辑处理工作

接下来看看实际的代码:

  • spring中的事件类 ApplicationEvent image.png
  • 初始化多播器 SimpleApplicationEventMulticaster
protected void initApplicationEventMulticaster() {
   // 获取当前bean工厂,一般是DefaultListableBeanFactory
   ConfigurableListableBeanFactory beanFactory = getBeanFactory();
   // 判断容器中是否存在bdName为applicationEventMulticaster的bd,也就是说自定义的事件监听多路广播器,必须实现ApplicationEventMulticaster接口
   if (beanFactory.containsLocalBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME)) {
      // 如果有,则从bean工厂得到这个bean对象
      this.applicationEventMulticaster =
            beanFactory.getBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, ApplicationEventMulticaster.class);
      if (logger.isTraceEnabled()) {
         logger.trace("Using ApplicationEventMulticaster [" + this.applicationEventMulticaster + "]");
      }
   }
   else {
      // 如果没有,则默认采用SimpleApplicationEventMulticaster
      this.applicationEventMulticaster = new SimpleApplicationEventMulticaster(beanFactory);
      beanFactory.registerSingleton(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, this.applicationEventMulticaster);
      if (logger.isTraceEnabled()) {
         logger.trace("No '" + APPLICATION_EVENT_MULTICASTER_BEAN_NAME + "' bean, using " +
               "[" + this.applicationEventMulticaster.getClass().getSimpleName() + "]");
      }
   }
}

多播器中的监听器集合在父类 AbstractApplicationEventMulticaster的内部类中:

image.png

  • spring中的监听器对象

image.png

  • 向多播器中注册进去已有的监听器
// Check for listener beans and register them.
// 在所有注册的bean中查找listener bean,注册到消息广播器中
registerListeners();
/**
    * 注册监听器
    *
    * Add beans that implement ApplicationListener as listeners.
    * Doesn't affect other listeners, which can be added without being beans.
    */
   protected void registerListeners() {
      // Register statically specified listeners first.
      // 遍历应用程序中存在的监听器集合,并将对应的监听器添加到监听器的多路广播器中
      for (ApplicationListener<?> listener : getApplicationListeners()) {
         getApplicationEventMulticaster().addApplicationListener(listener);
      }

      // Do not initialize FactoryBeans here: We need to leave all regular beans
      // uninitialized to let post-processors apply to them!
      // 从容器中获取所有实现了ApplicationListener接口的bd的bdName
      // 放入ApplicationListenerBeans集合中
      String[] listenerBeanNames = getBeanNamesForType(ApplicationListener.class, true, false);
      for (String listenerBeanName : listenerBeanNames) {
         getApplicationEventMulticaster().addApplicationListenerBean(listenerBeanName);
//       getApplicationEventMulticaster().addApplicationListener(this.getBean(listenerBeanName,ApplicationListener.class));
      }

      // Publish early application events now that we finally have a multicaster...
      // 此处先发布早期的监听器集合
      Set<ApplicationEvent> earlyEventsToProcess = this.earlyApplicationEvents;
      this.earlyApplicationEvents = null;
      if (!CollectionUtils.isEmpty(earlyEventsToProcess)) {
         for (ApplicationEvent earlyEvent : earlyEventsToProcess) {
            getApplicationEventMulticaster().multicastEvent(earlyEvent);
         }
      }
   }
  • 准备事件发布,来通知多播器循环调用监听器进行相关的逻辑处理工作 在完成刷新的时候会调用 publishEvent 发布最终事件
/**
 * 完成刷新
 * Finish the refresh of this context, invoking the LifecycleProcessor's
 * onRefresh() method and publishing the
 * {@link org.springframework.context.event.ContextRefreshedEvent}.
 */
protected void finishRefresh() {
   // Clear context-level resource caches (such as ASM metadata from scanning).
   // 清除上下文级别的资源缓存(如扫描的ASM元数据)
   // 清空在资源加载器中的所有资源缓存
   clearResourceCaches();

   // Initialize lifecycle processor for this context.
   // 为这个上下文初始化生命周期处理器
   // 初始化LifecycleProcessor.如果上下文中找到'lifecycleProcessor'的LifecycleProcessor Bean对象,
   // 则使用DefaultLifecycleProcessor
   initLifecycleProcessor();

   // Propagate refresh to lifecycle processor first.
   // 首先将刷新传播到生命周期处理器
   // 上下文刷新的通知,例如自动启动的组件
   getLifecycleProcessor().onRefresh();

   // Publish the final event.
   // 发布最终事件
   // 新建ContextRefreshedEvent事件对象,将其发布到所有监听器。
   publishEvent(new ContextRefreshedEvent(this));

   // Participate in LiveBeansView MBean, if active.
   // 参与LiveBeansView MBean,如果是活动的
   // LiveBeansView:Sping用于支持JMX 服务的类
   // 注册当前上下文到LiveBeansView,以支持JMX服务
   LiveBeansView.registerApplicationContext(this);
}

publishEvent方法调用过程中会调用 multicastEvent 多播applicationEvent到适当的监听器

// 多播applicationEvent到适当的监听器
getApplicationEventMulticaster().multicastEvent(applicationEvent, eventType);

最终在 doInvokeListener方法中会调用 listener.onApplicationEvent(event);

/**
 * 回调listener的onApplicationEvent方法,传入 event
 * @param listener
 * @param event
 */
@SuppressWarnings({"rawtypes", "unchecked"})
private void doInvokeListener(ApplicationListener listener, ApplicationEvent event) {
   try {
      //回调listener的onApplicationEvent方法,传入event:contextrefreshListener:onapplicaitonEvent:FrameworkServlet.this.onApplicationEvent()
      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.isTraceEnabled()) {
            logger.trace("Non-matching event type for listener: " + listener, ex);
         }
      }
      else {
         //抛出异常
         throw ex;
      }
   }
}