Spring Event 的幕后

简介: Spring Event 基于观察者模式,实现模块间松散耦合的通信。通过事件(Event)、事件发布者(Publisher)和事件监听器(Listener)三个核心组件,Spring Event 可以轻松实现业务解耦。Spring 容器在启动时会初始化 `ApplicationEventMulticaster`,扫描并注册所有事件监听器,通过调用 `multicastEvent()` 方法将事件广播给所有注册的监听器。

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

观察者模式

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

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

Spring Event

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

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

具体实现

  • 事件(Event)

java

代码解读

复制代码

@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)

java

代码解读

复制代码

applicationEventPublisher.publishEvent(new TypeComputationEvent(this"orderNo","status"))

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

  • 事件监听器(Listener)

java

代码解读

复制代码

@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 注解将事件处理逻辑异步化。

java

代码解读

复制代码

@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 容器初始化过程中被创建

java

代码解读

复制代码

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 容器初始化过程中被创建

java

代码解读

复制代码

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() 方法,会将事件传递给所有匹配的监听器。

java

代码解读

复制代码

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

相关文章
|
3月前
|
监控 Java C#
Spring Event 的介绍
Spring Event 是 Spring 框架中的事件驱动机制,允许组件间进行同步或异步消息传递,无需直接依赖。它包括事件(Event)、事件发布者(Publisher)和事件监听器(Listener),通过 `ApplicationEventPublisher` 广播事件,实现松耦合通信,增强模块化和可维护性。Spring 还提供了多种内置事件,如 `ContextRefreshedEvent` 和 `ContextClosedEvent`,支持同步及异步处理,并具备良好的扩展性。
|
缓存 Java 开发者
Spring高手之路15——掌握Spring事件监听器的内部逻辑与实现
深入探索Spring的事件处理机制,从事件的层次传播、PayloadApplicationEvent的使用,到为何选择自定义事件。本文详细剖析了Spring 5.x的事件模型、事件发布源码、ApplicationEventMulticaster的作用以及事件广播的核心逻辑。通过详细的流程图与图示,读者可以更好地理解Spring事件传播、异步处理等关键概念,为成为Spring高手奠定坚实基础。
28888 26
Spring高手之路15——掌握Spring事件监听器的内部逻辑与实现
|
设计模式 Java 数据库连接
Spring高手之路7——事件机制与监听器的全面探索
本篇文章为你详细解析了Spring的事件机制,包括了Spring事件模型的四个核心概念:事件源、事件、广播器、监听器。我们通过深入浅出的实例解析了如何自定义事件和监听器,以及如何在实际项目中应用。最后,我们还详细探讨了监听器和Bean的生命周期的关系。无论你是Spring初学者,还是有一定经验的开发者,阅读本文都将帮助你更深入地理解Spring的事件机制和监听器,掌握Spring框架的核心技术。
1182 0
Spring高手之路7——事件机制与监听器的全面探索
|
设计模式 缓存 Java
深入理解Spring IOC之扩展篇(七)、Spring中的event以及自定义event
深入理解Spring IOC之扩展篇(七)、Spring中的event以及自定义event
121 0
|
XML Java 数据格式
深入理解Spring IOC之扩展篇(九)、SpringBoot中重要event介绍,顺便简单讲下SB的启动流程(一)
深入理解Spring IOC之扩展篇(九)、SpringBoot中重要event介绍,顺便简单讲下SB的启动流程(一)
120 0
|
Java Spring
深入理解Spring IOC之扩展篇(十)、SpringBoot中重要event介绍,顺便简单讲下SB的启动流程(二)
深入理解Spring IOC之扩展篇(十)、SpringBoot中重要event介绍,顺便简单讲下SB的启动流程(二)
118 0
|
消息中间件 JavaScript 小程序
Spring Event + DDD = 王炸!!下
Spring Event + DDD = 王炸!!下
|
存储 JavaScript 小程序
Spring Event + DDD = 王炸!!上
Spring Event + DDD = 王炸!!上
|
设计模式 数据可视化 Java
Spring 事件处理机制详解,带你吃透 Spring 事件
前言 Spring 事件处理基于 Java 观察者模式扩展。Spring 应用上下文中发布了各种事件,此外 Spring 还允许我们发送和处理自定义的事件,本篇将对 Spring 的事件机制使用及其实现进行详细介绍。
1336 0
Spring 事件处理机制详解,带你吃透 Spring 事件
|
Java Spring 微服务
Spring event 使用完全指南
说明 此篇文章以 Spring 4.2+ 为例,在此版本之前略微有不同。笔者自2014年起开始接触和使用 Spring event,根据 Spring event 的原理开发了 JFinal-event: https://gitee.com/596392912/JFinal-event ,方便 JFinal 用户使用,JFinal event 2.x 也同步成 Spring 4.2.x+ 的使用方式,不再需要创建多个 Listener 类,使用更加简单方便。
3480 0

热门文章

最新文章