Spring中事件机制的实现示例

 更新时间:2025年10月09日 08:30:33   作者:我也有鱼鱼蒸  
Spring中的事件机制是基于观察者模式实现的一种组件间通信机制,用于解耦不同组件,实现松耦合的消息传递,下面就来了解一下Spring中事件机制的实现,感兴趣的可以了解一下

Spring中的事件机制是基于观察者模式实现的一种组件间通信机制,用于解耦不同组件,实现松耦合的消息传递,它允许一个组件发送事件,其他组件接收并处理事件,而无需直接依赖彼此。

事件机制的组成

Spring事件机制包含三个核心部分:

  • 事件:继承ApplicationEvent的对象,封装需要传递的数据。Spring4.2+可以省略,任意对象都可以作为事件。
  • 事件发布者:通过ApplicationEventPublisher接口发布事件,通常由spring管理的bean实现。
  • 事件监听器:监听并处理事件的组件,通过@EventListener注解或实现ApplicationListener接口定义。

示例

事件:

首先自定义一个事件类,去实现ApplicationEvent,该父类没有无参构造:

public class MyEvent extends ApplicationEvent {
    
    public MyEvent(Object source) {
        super(source);
    }
}

发布者:

在业务代码内注入ApplicationEventPublisher,通过它去发布事件:

@Autowired
    private ApplicationEventPublisher applicationEventPublisher;
    public void enent(){
        //业务代码
        //发送事件
        applicationEventPublisher.publishEvent(new MyEvent(this));
    }

监听器:

监听事件类型,两种方式都试一遍:

@Component
public class MyLin implements ApplicationListener<MyEvent> {
    @Override
    public void onApplicationEvent(MyEvent event) {
        System.out.println("监听到事件");
    }
}
@Component
public class MyLin2 {
    //注意方法的参数类型是监听的类型
    @EventListener
    public void onApplicationEvent(MyEvent event) {
        System.out.println("监听到事件2");
    }
}

接下来模拟异步的情况:

SimpleApplicationEventMulticaster

SimpleApplicationEventMulticaster是 Spring 框架中事件机制的核心组件,负责将发布的事件多播(multicast) 给所有订阅该事件的监听器,是事件从发布者传递到监听器的 “中介”。

它的主要职责是:

  1. 接收发布者发布的事件;
  2. 找到所有监听该事件类型的监听器;
  3. 将事件分发给这些监听器执行处理逻辑。

特性:

  • 事件发布后,它会直接发布在事件的线程中调研监听器的处理方法,发布者需等待所有的监听器完毕后才能继续,可以过setTaskExector(Executor)设置线程池,会将监听器的处理逻辑交到线程池执行,发布者无需等待。
  • 支持通过 addApplicationListener(ApplicationListener) 手动注册监听器;

配置好SimpleApplicationEventMulticaster后,通过ApplicationEventPublish发送事件后会提交到配置的线程池中执行。

    @Bean
    public SimpleApplicationEventMulticaster applicationEventMulticaster(ThreadPoolExecutor executor){
        SimpleApplicationEventMulticaster multicaster = new SimpleApplicationEventMulticaster();
        multicaster.setTaskExecutor(executor);
        return multicaster;
    }

异步事件监听器

@Component
public class AsyncEventListener {
    
    private static final Logger logger = LoggerFactory.getLogger(AsyncEventListener.class);
    
    /**
     * 异步处理事件 - 不会阻塞主线程
     */
    @Async("taskExecutor")  // 指定使用配置的线程池
    @EventListener
    public void handleAsyncEvent(MyEvent event) {
        logger.info("异步事件处理开始 - 事件: {}", event.getMessage());
        logger.info("当前线程: {}", Thread.currentThread().getName());
        
        try {
            // 模拟耗时操作
            Thread.sleep(3000);
            logger.info("异步事件处理完成: {}", event.getMessage());
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
            logger.error("异步事件处理被中断", e);
        }
    }
    
    /**
     * 同步处理事件 - 会阻塞主线程
     */
    @EventListener
    public void handleSyncEvent(MyEvent event) {
        logger.info("同步事件处理开始 - 事件: {}", event.getMessage());
        logger.info("当前线程: {}", Thread.currentThread().getName());
        
        try {
            // 模拟耗时操作
            Thread.sleep(2000);
            logger.info("同步事件处理完成: {}", event.getMessage());
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
            logger.error("同步事件处理被中断", e);
        }
    }
}
@SpringBootTest
public class EventTest {
    
    @Autowired
    private BusinessService businessService;
    
    @Test
    public void testAsyncEvent() {
        System.out.println("测试开始 - 主线程: " + Thread.currentThread().getName());
        
        long startTime = System.currentTimeMillis();
        businessService.doBusiness();
        long endTime = System.currentTimeMillis();
        
        System.out.println("业务方法执行时间: " + (endTime - startTime) + "ms");
        
        // 给异步事件处理留出时间
        try {
            Thread.sleep(5000);
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        }
    }
}

Spring 内置事件

Spring 框架自带一些内置事件,用于通知容器生命周期的关键节点,常见的有:

事件类型触发时机
ContextRefreshedEventSpring 容器初始化完成(所有 Bean 加载完成)
ContextStartedEvent容器启动时(调用start()方法)
ContextStoppedEvent容器停止时(调用stop()方法)
ContextClosedEvent容器关闭时(调用close()方法)
ApplicationFailedEvent应用启动失败时(Spring Boot 中常用)

到此这篇关于Spring中事件机制的实现示例的文章就介绍到这了,更多相关Spring 事件机制内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • mybatis if标签使用总结

    mybatis if标签使用总结

    这篇文章主要介绍了mybatis if标签使用总结,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2019-12-12
  • 使用Java实现在Excel中添加动态数组公式

    使用Java实现在Excel中添加动态数组公式

    动态数组公式是 Excel 引入的一项重要功能,它允许用户从单个单元格中的公式返回多个结果值,并将这些值自动填充到与公式单元格相邻的单元格中,本文主要介绍了如何使用Java实现在Excel中添加动态数组公式,x需要的可以参考下
    2023-12-12
  • 解决SpringBoot2.1.0+RocketMQ版本冲突问题

    解决SpringBoot2.1.0+RocketMQ版本冲突问题

    这篇文章主要介绍了解决SpringBoot2.1.0+RocketMQ版本冲突问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2024-06-06
  • 基于XML的Spring声明事务控制

    基于XML的Spring声明事务控制

    这篇文章主要为大家详细介绍了基于XML的Spring声明事务控制,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-07-07
  • java9学习系列之在docker中如何运行java9

    java9学习系列之在docker中如何运行java9

    最近在学习java9,所以将学习中遇到的一些知识点分享给大家,下面这篇文章主要给大家介绍了java9学习系列之在docker中如何运行java9的相关资料,文中通过示例代码介绍的非常详细,需要的朋友可以参考下。
    2017-09-09
  • Java日常练习题,每天进步一点点(62)

    Java日常练习题,每天进步一点点(62)

    下面小编就为大家带来一篇Java基础的几道练习题(分享)。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧,希望可以帮到你
    2021-08-08
  • Java成员变量与局部变量(动力节点Java学院整理)

    Java成员变量与局部变量(动力节点Java学院整理)

    这篇文章主要介绍了Java成员变量与局部变量的相关资料,非常不错,具有参考借鉴价值,需要的朋友可以参考下
    2017-04-04
  • java基础之NIO介绍及使用

    java基础之NIO介绍及使用

    这篇文章主要介绍了java基础之NIO介绍及使用,文中有非常详细的代码示例,对正在学习java基础的小伙伴们有非常好的帮助,需要的朋友可以参考下
    2021-04-04
  • Spring的RedisTemplate存储的key和value有特殊字符的处理

    Spring的RedisTemplate存储的key和value有特殊字符的处理

    这篇文章主要介绍了Spring的RedisTemplate存储的key和value有特殊字符的处理方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2023-12-12
  • Java中的StringBuilder()常见方法详解

    Java中的StringBuilder()常见方法详解

    StringBuilder是一个可变的字符序列,此类提供一个与 StringBuffer 兼容的 API,但不保证同步,这篇文章主要介绍了StringBuilder()常见方法,需要的朋友可以参考下
    2023-09-09

最新评论