Spring Event 基于发布-订阅模式(观察者模式),使得系统中不同模块可以通过事件进行松散耦合的通信,而不需要直接依赖彼此,使用Spring Event,可以轻松实现业务解耦。

观察者模式

  观察者模式(Observer Pattern)是一种行为设计模式,它定义了一种一对多的依赖关系,使得一个对象(被观察者,Subject)可以通知多个观察者(Observers)对象,在其状态发生变化时,所有依赖它的对象都会收到通知并自动更新。

  观察者模式中有四个角色(一般情况):目标、具体目标、观察者、具体观察者。在JDK中使用Observer接口和Observable类来作为观察者模式的抽象层,再自定义具体观察者类和具体观察目标类,可以方便地应用观察者模式。

Spring Event

为什么前面要简单的回顾了观察者模式呢?

  事实上,Spring Event 是观察者模式的一种具体实现。Spring Event 机制的设计围绕三个核心组件展开:事件(Event)、事件发布者(Publisher)和事件监听器(Listener)。

具体实现

  • 事件(Event)
@Getter
public class TypeComputationEvent extends ApplicationEvent {

    String orderNo;
    String status;

    public TypeComputationEvent(Object source,String orderNo,String status) {
        super(source);
        this.orderNo = orderNo;
        this.status = status;
    }
}

  事件是系统中某个动作或状态改变的标识,在 Spring 中,事件通常是一个继承自 ApplicationEvent 的类。

  • 事件发布者(Publisher)
applicationEventPublisher.publishEvent(new TypeComputationEvent(this,"orderNo","status"))

  事件发布者是触发事件的组件,在 Spring 中,任何组件都可以充当事件发布者,只需要通过依赖注入的方式获取 ApplicationEventPublisher 的实例,然后调用其 publishEvent() 方法发布事件。

  • 事件监听器(Listener)
@Slf4j
@Component
@RequiredArgsConstructor
@FieldDefaults(level = AccessLevel.PRIVATE, makeFinal = true)
public class TypeComputationListener {

    @EventListener
    public void onApplicationEvent(TypeComputationEvent event) {
        log.info("=====>>>订单状态变更事件,订单号:{}", event.getOrderNo());

    }

}

  事件监听器用于当事件发布后,所有监听该事件的监听器都会被触发并执行相应的处理逻辑。Spring 提供了 @EventListener 注解,只需将其标注在方法上,该方法就会在相应事件发生时自动执行。@TransactionalEventListener注解 通过与 Spring 的事务管理器集成,使得事件处理与事务的生命周期紧密相关。具体来说,它允许你指定在事务提交前或后处理事件。

  默认情况下,ApplicationListener处理事件是同步执行的,在某些情况下,事件处理逻辑可能会比较耗时,为了避免阻塞主线程,可以通过 @Async 注解将事件处理逻辑异步化。

@Slf4j
@Component
@RequiredArgsConstructor
@FieldDefaults(level = AccessLevel.PRIVATE, makeFinal = true)
public class TypeComputationListener {

    @EventListener
    @Async
    public void onApplicationEvent(TypeComputationEvent event) {
        log.info("=====>>>订单状态变更事件,订单号:{}", event.getOrderNo());

    }

}

实现原理

  Spring 的事件处理机制涉及到 ApplicationEventMulticaster 组件,这个组件是事件发布和监听的核心部分。

  • ApplicationEventMulticaster 初始化,在 Spring 容器初始化过程中被创建
protected void initApplicationEventMulticaster() {
   ConfigurableListableBeanFactory beanFactory = getBeanFactory();
   // 如果手动新建了一个ApplicationEventMulticaster类型为的bean,则将这个bean作为事件广播器
   if (beanFactory.containsLocalBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME)) {
      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() + "]");
      }
   }
}
  • registerListeners 注册监听器,在 Spring 容器初始化过程中被创建
protected void registerListeners() {
   // 把监听器添加到监听器容器中
   for (ApplicationListener<?> listener : getApplicationListeners()) {
      getApplicationEventMulticaster().addApplicationListener(listener);
   }

   // 获取类型是ApplicationListener的beanName集合
   String[] listenerBeanNames = getBeanNamesForType(ApplicationListener.class, true, false);
   for (String listenerBeanName : listenerBeanNames) {
      getApplicationEventMulticaster().addApplicationListenerBean(listenerBeanName);
   }

   
   Set<ApplicationEvent> earlyEventsToProcess = this.earlyApplicationEvents;
   this.earlyApplicationEvents = null;
   if (!CollectionUtils.isEmpty(earlyEventsToProcess)) {
      for (ApplicationEvent earlyEvent : earlyEventsToProcess) {
         getApplicationEventMulticaster().multicastEvent(earlyEvent);
      }
   }
}

  Spring 容器在启动时会扫描所有的 @EventListener 注解或实现了 ApplicationListener 接口的类,并将这些监听器注册到 ApplicationEventMulticaster 中。

  • multicastEvent发布事件

  当我们通过applicationEventPublisher.publishEvent()发布事件时,会调用 ApplicationEventMulticaster.multicastEvent() 方法,会将事件传递给所有匹配的监听器。

public void multicastEvent(final ApplicationEvent event, @Nullable ResolvableType eventType) {
   ResolvableType type = (eventType != null ? eventType : resolveDefaultEventType(event));
   Executor executor = getTaskExecutor();
   for (ApplicationListener<?> listener : getApplicationListeners(event, type)) {
      if (executor != null) {
         executor.execute(() -> invokeListener(listener, event));
      }
      else {
         invokeListener(listener, event);
      }
   }
}

总结

  Spring Event 通过 Spring 容器初始化时创建并配置 ApplicationEventMulticaster 实例,扫描并注册所有事件监听器(通过注解或接口实现)。最后通过调用 multicastEvent() 方法,将事件广播给所有注册的监听器。Spring Event 它基于观察者模式实现,通过事件驱动的方式实现了模块间的松散耦合。


转载来源:https://juejin.cn/post/7402435366647119881