springboot 事件监听@EventListener注解用法

发布时间 2023-04-19 20:00:50作者: DaenMax

前言

关于@EventListener注解,百度了一下,网上的教程很多都是继承这个,实现那个的,其实根本用不着这么麻烦,所以就写了此文,如文章所讲有误,还请谅解
更多详细用法请百度一下~

作用

关于事件监听,目前我的用法最多的就是记录日志之类的。
在此之前我们记录日志一般都是先把日志的service注入进来,然后调用,其实我们可以写的更优雅一点,那就是用@EventListener

开始

建一个实体类

package cn.daenx.myadmin.system.vo;
import lombok.Data;

@Data
public class TestEventVo {
    private String title;
    private String content;
}

建一个处理方法

我一般在impl里

    @EventListener(classes = TestEventVo.class) //这个参数可以省略
    public void handle1(TestEventVo testEventVo) {
        log.info("进入handle1");
        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
        log.info("title为{}", testEventVo.getTitle());
        log.info("结束handle1");
    }

建一个接口

    @GetMapping("/event")
    public Result event() {
        log.info("接收到前端请求");
        TestEventVo testEventVo = new TestEventVo();
        testEventVo.setTitle("我是标题");
        //获取上下文,这里用的是Hutool里的工具类
        SpringUtil.getApplicationContext().publishEvent(testEventVo);
        log.info("即将响应给前端");
        return Result.ok();
    }

结果

调用一下这个接口

可以看到,我们的处理方法被正确执行了

结论

1.每个事件以实体类区分,在你的处理方法上添加注解@EventListener,方法的参数就是你用的实体类
2.处理方法执行完后,才会返回给前端,说明是同步处理
注意,处理方法只能有这实体类一个参数,如果有多个参数的话,项目会起不来

扩展

异步处理

可以通过在处理方法上添加注解@Async实现异步处理

    @Async
    @EventListener(classes = TestEventVo.class)
    public void handle1(TestEventVo testEventVo) {
        log.info("进入handle1");
        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
        log.info("title为{}", testEventVo.getTitle());
        log.info("结束handle1");
    }

多个处理方法时?

    @EventListener(classes = TestEventVo.class)//参数可以省略
    public void handle1(TestEventVo testEventVo) {
        log.info("进入handle1");
        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
        log.info("title为{}", testEventVo.getTitle());
        log.info("结束handle1");
    }

    @EventListener
    public void handle2(TestEventVo testEventVo) {
        log.info("进入handle2");
        try {
            Thread.sleep(5000);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
        log.info("title为{}", testEventVo.getTitle());
        log.info("结束handle2");
    }

结果

通过观察日志时间,可以看到,
1.一个实体类有多个处理方法时,都会被执行
2.多个处理方法是单线程执行的,一个执行完了,另一个才会开始执行
3.所有处理方法都执行完后,才会返回给前端