Spring事件驱动

refresh() -> initApplicationEventMulticaster()

初始化事件监听多路广播器

观察者模式

观察者模式使用三个类 Subject、Observer 和 Client。Subject 对象带有绑定观察者到 Client 对象和从 Client 对象解绑观察者的方法。我们创建 Subject 类、Observer 抽象类和扩展了抽象类 Observer 的实体类。

ObserverPatternDemo,我们的演示类使用 Subject 和实体类对象来演示观察者模式。在这里插入图片描述

  • Observer:观察者
  • Subject:被观察者

观察者观察被观察者,当被观察者作出特定动作则循环执行观察者集合中特定方法,方法中根据动作判断是否需要执行特定操作

Spring中的观察者模式(事件驱动)

  • 事件:被观察者具体要执行的动作
  • 监听器:观察者,可能存在多个,接收不同的事件来处理不同的动作
  • 多播器:被观察者遍历观察者通知消息的操作拿出来委托给一个多播器来进行消息通知,或者说通过观察者进行不同的操作
  • 事件源:谁来调用或者指定发布具体的事件

逻辑执行过程

  1. 事件源来发布不同的事件
  2. 当发布事件之后会调用多播器的方法来进行事件广播操作,由多播器去触发具体的监听器去执行操作
  3. 监听器接收到具体的事件之后,可以验证匹配是否能处理当前事件,如果可以,直接处理,如果不行,不做任何操作

实际代码处理

  1. 提前准备好n多个事件
  2. 初始化多播器(创建多播器对象,此多播器对象中应该包含一个监听器的集合)
  3. 准备好一系列的监听器
  4. 向多播器中注册进去已有的监听器
  5. 准备事件发布,来通知多播器循环调用监听器进行相关的逻辑处理工作

initApplicationEventMulticaster()

初始化多播器/广播器(ApplicationEventMulticaster)如果上下文中没有定义,则使用SimpleApplicationEventMulticaster

protected void initApplicationEventMulticaster() {
  // 获取当前bean工厂,一般是DefaultListableBeanFactory
  ConfigurableListableBeanFactory beanFactory = getBeanFactory();
  //bd -> BeanDefinition
  // 判断容器中是否存在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() + "]");
    }
  }
}

SimpleApplicationEventMulticaster

将所有事件多播给所有注册的监听器,让监听器忽略它们不感兴趣的事件。监听器通常会对传入的事件对象执行相应的 instanceof 检查。默认情况下,所有监听器都在调用线程中调用。这允许恶意监听器阻塞整个应用程序的危险,但只增加最小的开销。指定另一个任务执行器,让监听器在不同的线程中执行

在这里插入图片描述

  • ApplicationEventMulticaster:接口的实现类可以管理多个ApplicationListener监听器对象,并且发布事件到监听器

  • AbstractApplicationEventMulticaster:是ApplicationEventMulticaster接口的抽象实现,提供基本的监听器注册工具方法(注册和移除监听器)默认情况下不允许同一个监听器有多个实例,因为该类会将监听器保存在ListenerRetriever集合类的set集合中

    // 创建监听器助手类,用于存放应用程序的监听器集合,参数是否是预过滤监听器为false
    private final ListenerRetriever defaultRetriever = new ListenerRetriever(false);
    
  • ListenerRetriever:封装特定目标监听器的 Hellper 类,允许高效地检索预过滤的监听器

    private class ListenerRetriever {
    		// ApplicationListener 对象集合
    		public final Set<ApplicationListener<?>> applicationListeners = new LinkedHashSet<>();
    		.......
    }
    

refresh() -> registerListeners()

在所有注册的bean中查找listener bean,注册到消息广播器中

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...
  // 此处先发布早期的监听器集合(前戏prepareRefresh()已经初始化earlyApplicationEvents)
  Set<ApplicationEvent> earlyEventsToProcess = this.earlyApplicationEvents;
  this.earlyApplicationEvents = null;
  if (!CollectionUtils.isEmpty(earlyEventsToProcess)) {
    for (ApplicationEvent earlyEvent : earlyEventsToProcess) {
      getApplicationEventMulticaster().multicastEvent(earlyEvent);
    }
  }
}

refresh() -> finishRefresh() -> publishEvent()

事件源:发布最终事件

// 新建ContextRefreshedEvent事件对象,将其发布到所有监听器
publishEvent(new ContextRefreshedEvent(this));

将给定事件发布到所有监听器

@Override
public void publishEvent(ApplicationEvent event) {
   publishEvent(event, null);
}

将给定事件发布到所有监听器

protected void publishEvent(Object event, @Nullable ResolvableType eventType) {
   // 如果event为null,抛出异常
   Assert.notNull(event, "Event must not be null");

   // Decorate event as an ApplicationEvent if necessary
   // 装饰事件作为一个应用事件,如果有必要
   ApplicationEvent applicationEvent;
   // 如果event是ApplicationEvent的实例
   if (event instanceof ApplicationEvent) {
      // 将event强转为ApplicationEvent对象
      applicationEvent = (ApplicationEvent) event;
   }
   else {
      // PayloadApplicationEvent:携带任意有效负载的ApplicationEvent。
      // 创建一个新的PayloadApplicationEvent
      applicationEvent = new PayloadApplicationEvent<>(this, event);
      // 如果eventType为 null
      if (eventType == null) {
         // 将applicationEvent转换为PayloadApplicationEvent 象,引用其ResolvableType对象
         eventType = ((PayloadApplicationEvent<?>) applicationEvent).getResolvableType();
      }
   }

   // Multicast right now if possible - or lazily once the multicaster is initialized
   // 如果可能的话,现在就进行组播——或者在组播初始化后延迟
   // earlyApplicationEvents:在多播程序设置之前发布的ApplicationEvent
   // 如果earlyApplicationEvents不为 null,这种情况只在上下文的多播器还没有初始化的情况下才会成立,会将applicationEvent
   // 添加到earlyApplicationEvents保存起来,待多博器初始化后才继续进行多播到适当的监听器
   if (this.earlyApplicationEvents != null) {
      //将applicationEvent添加到 earlyApplicationEvents
      this.earlyApplicationEvents.add(applicationEvent);
   }
   else {
      // 多播applicationEvent到适当的监听器
      getApplicationEventMulticaster().multicastEvent(applicationEvent, eventType);
   }

   // Publish event via parent context as well...
   // 通过父上下文发布事件
   // 如果parent不为null
   if (this.parent != null) {
      // 如果parent是AbstractApplicationContext的实例
      if (this.parent instanceof AbstractApplicationContext) {
         // 将event多播到所有适合的监听器。如果event不是ApplicationEvent实例,会将其封装成PayloadApplicationEvent对象再进行多播
         ((AbstractApplicationContext) this.parent).publishEvent(event, eventType);
      }
      else {
         // 通知与event事件应用程序注册的所有匹配的监听器
         this.parent.publishEvent(event);
      }
   }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值