spring @EventListener 事件与监听的示例详解

 更新时间:2025年03月05日 11:38:17   作者:xixingzhe2  
本文介绍了自定义Spring事件和监听器的方法,包括如何发布事件、监听事件以及如何处理异步事件,通过示例代码和日志,展示了事件的顺序执行和异步处理机制,感兴趣的朋友一起看看吧

1、自定义Application Event

package com.ybw.event.pojo;
import lombok.Getter;
import lombok.Setter;
import org.springframework.context.ApplicationEvent;
/**
 * @className MyEvent
 * @author weixiansheng
 * @date 2023/9/28 
 * @version V1.0
 **/
@Setter
@Getter
public class MyEvent extends ApplicationEvent {
    private String data;
    public MyEvent(Object source, String data) {
        super(source);
        this.data = data;
    }
}

2、自定义监听

package com.ybw.event.listener;
import com.ybw.event.pojo.MyEvent;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Component;
/**
 * 简单监听
 *
 * @author weixiansheng
 * @version V1.0
 * @className MySimpleListener
 * @date 2023/9/28
 **/
@Component
@Slf4j
public class MySimpleListener {
    /**
     * @param event
     * @methodName: handleDemoEvent
     * @return: void
     * @author: weixiansheng
     * @date: 2023/9/28
     **/
    @EventListener
    public void handleDemoEvent(MyEvent event) {
        log.info("发布的data为:{}", event.getData());
    }
}

3、测试

package com.ybw.event.listener;
import com.ybw.event.pojo.MyEvent;
import com.ybw.util.SpringContextHolder;
import lombok.extern.slf4j.Slf4j;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
import java.util.concurrent.TimeUnit;
/**
 * @author weixiansheng
 * @version V1.0
 * @className MySimpleListenerTest
 * @date 2023/9/28
 **/
@SpringBootTest
@Slf4j
class MySimpleListenerTest {
    /**
     * 发布消息
     *
     * @methodName: publishEvent
     * @return: void
     * @author: weixiansheng
     * @date: 2023/9/28
     **/
    @Test
    public void publishEvent() throws InterruptedException {
        log.info("publishEvent start");
        SpringContextHolder.publishEvent(new MyEvent(this, "测试"));
        log.info("publishEvent end");
        TimeUnit.DAYS.sleep(1);
    }
}

打印日志

[INFO ] 2023-09-28 10:19:15.312 [main] c.y.e.listener.MySimpleListenerTest - publishEvent start
[INFO ] 2023-09-28 10:19:16.344 [main] c.y.event.listener.MySimpleListener - 发布的data为:测试
[INFO ] 2023-09-28 10:19:16.347 [main] c.y.e.listener.MySimpleListenerTest - publishEvent end

4、源代码

share: 分享仓库 - Gitee.com

5、其他

5.1 顺序执行

使用注解

  • @Order order的值越小,优先级越高。
  • order如果不标注数字,默认最低优先级,因为其默认值是int最大值。

示例

/**
 * 普通监听
 *
 * @param event
 * @methodName: handleDemoEvent
 * @return: void
 * @author: weixiansheng
 * @date: 2023/9/28
 **/
@EventListener
@Order(2)
public void handleEvent(MyEvent event) throws InterruptedException {
    TimeUnit.SECONDS.sleep(1);
    log.info("handleEvent data:{}", event.getData());
}
/**
 * 条件监听
 *
 * @param event
 * @methodName: handleConditionEvent
 * @return: void
 * @author: weixiansheng
 * @date: 2023/9/28
 **/
@EventListener(condition = "#event.data=='张三'")
@Order(1)
public void handleConditionEvent(MyEvent event) {
    log.info("handleConditionEvent data:{}", event.getData());
}

打印日志

[INFO ] 2023-09-28 10:40:22.206 [main] c.y.event.listener.MySimpleListener - handleConditionEvent data:张三
[INFO ] 2023-09-28 10:40:23.216 [main] c.y.event.listener.MySimpleListener - handleEvent data:张三

 5.2 异步支持

        Spring 事件机制默认是同步阻塞的,如果 ApplicationEventPublisher 发布事件之后他会一直阻塞等待listener 响应,多个 listener 的情况下前面的没有执行完后面的会一直被阻塞。发布者和订阅者属于同一事务,如果订阅者执行失败了,发布者事务会回滚。

        可以利用 Spring 提供的线程池注解 @Async 来实现异步线程。异步不影响发布者的事务。

示例

/**
 * 普通监听
 *
 * @param event
 * @methodName: handleDemoEvent
 * @return: void
 * @author: weixiansheng
 * @date: 2023/9/28
 **/
@EventListener
public void handleEvent(MyEvent event) throws InterruptedException {
    TimeUnit.SECONDS.sleep(1);
    log.info("handleEvent data:{}", event.getData());
}
/**
 * 条件监听
 *
 * @param event
 * @methodName: handleConditionEvent
 * @return: void
 * @author: weixiansheng
 * @date: 2023/9/28
 **/
@Async
@EventListener(condition = "#event.data=='张三'")
public void handleConditionEvent(MyEvent event) {
    log.info("handleConditionEvent data:{}", event.getData());
}

打印日志

[INFO ] 2023-09-28 10:49:40.246 [thread-pool-1] com.ybw.event.listener.MyListener - handleConditionEvent data:张三
[INFO ] 2023-09-28 10:49:41.255 [main] com.ybw.event.listener.MyListener - handleEvent data:张三

一个是线程thread-pool-1,一个是线程main。 

6、总结

  • 事件模式概念
    • 事件:事件的触发者,比如用户注册就是事件。
    • 事件发布:描述发生了什么事情的对象,比如张三注册成功的事件。
    • 事件监听:监听到事件发生的时候,做一些处理,比如下单后,增加用户积分。
  • Spring中事件监听器的处理是同步方式
    • 日志都是都一个线程。
    • 执行时顺序的,执行完监听器的业务后,会向下继续执行后面的逻辑。如上例:publishEvent end。

到此这篇关于spring @EventListener 事件与监听的文章就介绍到这了,更多相关spring @EventListener 事件与监听内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Spring自动装配@Autowired教程

    Spring自动装配@Autowired教程

    @Autowired注解是Spring中非常重要且常见的,接下来就简要的介绍一下它的用法。@Autowired默认是通过set方法,按照类型自动装配JavaBean,set方法可省略不写,它主要是修饰在成员变量上
    2023-01-01
  • Spring Security实现5次密码错误触发账号自动锁定功能

    Spring Security实现5次密码错误触发账号自动锁定功能

    在现代互联网应用中,账号安全是重中之重,然而,暴力 破解攻击依然是最常见的安全威胁之一,攻击者通过自动化脚本尝试大量的用户名和密码组合,试图找到漏洞进入系统,所以为了解决这一问题,账号锁定机制被广泛应用,本文介绍了Spring Security实现5次密码错误触发账号锁定功能
    2024-12-12
  • Windows中使用Java生成Excel文件并插入图片的方法

    Windows中使用Java生成Excel文件并插入图片的方法

    这篇文章主要介绍了Windows中使用Java生成Excel文件并插入图片的方法,其中向Excel中插入图片文中通过使用Apache POI来实现,需要的朋友可以参考下
    2016-02-02
  • Java实现给图片添加图片水印,文字水印及马赛克的方法示例

    Java实现给图片添加图片水印,文字水印及马赛克的方法示例

    这篇文章主要介绍了Java实现给图片添加图片水印,文字水印及马赛克的方法,涉及java针对图片的读取、水印添加、马赛克设置等相关操作技巧,需要的朋友可以参考下
    2018-01-01
  • Spring-cloud-eureka使用feign调用服务接口

    Spring-cloud-eureka使用feign调用服务接口

    这篇文章主要为大家详细介绍了Spring-cloud-eureka使用feign调用服务接口,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2019-04-04
  • Maven脚手架如何基于jeecg实现快速开发

    Maven脚手架如何基于jeecg实现快速开发

    这篇文章主要介绍了Maven脚手架如何基于jeecg实现快速开发,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-10-10
  • ZooKeeper命令及JavaAPI操作代码

    ZooKeeper命令及JavaAPI操作代码

    ZooKeeper是一个树形目录服务,其数据模型和Uiix的文件目录树很类似,拥有一个层次化结构,这篇文章主要介绍了ZooKeeper命令及JavaAPI操作代码,需要的朋友可以参考下
    2023-03-03
  • java并发编程工具类JUC之LinkedBlockingQueue链表队列

    java并发编程工具类JUC之LinkedBlockingQueue链表队列

    大家都知道LinkedBlockingQueue 队列是BlockingQueue接口的实现类,所以它具有BlockingQueue接口的一切功能特点,他还提供了两种构造函数,本文中通过实例代码给大家介绍的非常详细,需要的朋友参考下吧
    2021-06-06
  • @Async异步线程池以及线程的命名方式

    @Async异步线程池以及线程的命名方式

    这篇文章主要介绍了@Async异步线程池以及线程的命名方式,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-06-06
  • Java中Lambda表达式用法介绍

    Java中Lambda表达式用法介绍

    本文详细讲解了Java中Lambda表达式的用法,文中通过示例代码介绍的非常详细。对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2021-12-12

最新评论