前言
关于@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.所有处理方法都执行完后,才会返回给前端