spring中的事件发布与监听
点赞再看,养成习惯,微信搜索「小大白日志」关注这个搬砖人。
文章不定期同步公众号,还有各种一线大厂面试原题、我的学习系列笔记。
spring事件发布与监听的应用场景
当处理完一段代码逻辑,接下来需要同时执行多个任务,有什么好方法呢?如果在微服务项目中,当属MQ莫属了;但如果是单机,spring为我们也提供了[事件发布-监听]机制去处理这种逻辑,主要有@EventListener型和@TransactionalEventListener型两种方式
@EventListener型发布与监听
一般有【实体类+事件类+事件发布类+事件监听类】,以下模拟“添加新用户”后,需要同时进行多个任务为例(异步)
//实体类
@Data
public class User {
private String name;
private String operate;
}
//事件类
@Setter
@Getter
public class UserEvent extends ApplicationEvent{ //事件类必须继承ApplicationEvent
private User user;
public UserEvent(Object source) {
super(source);
}
}
//事件发布类
@Service
@Slf4j
public class UserServiceImpl {
@Autowired
private ApplicationEventPublisher applicationEventPublisher;
public void addUser(){
User user=new User();
user.setName("afei");
user.setOperate("add");
UserEvent userEvent=new UserEvent(this);
userEvent.setUser(user);
insertUser(user);//user入库
applicationEventPublisher.publishEvent(userEvent);//"事件发布类"发布UserEvent事件以便给"事件监听类"监听到
log.info("{},发布[添加新用户]事件成功...",Thread.currentThread().getName());
}
public void insertUser(User user){}
}
//事件监听类
@Component //必须让spring扫描到
@Slf4j
public class UserListerner {
/*
*执行多任务
*/
@Async //@Async可以开启一个异步任务(启动类要加@EnableAsync),因为监听默认是同步的:监听到UserEvent类事件后,执行本方法代码,然后返回原链路继续执行原来的代码;有了@Async就可以以线程的方式异步执行本方法
@EventListener(value = UserEvent.class,condition = "#userEvent.user.operate=='add'") //只监听userEvent.user.operate='add'的UserEvent事件,#userEvent与afterAddUser()方法的参数名一致
public void afterAddUser(UserEvent userEvent){
try {
Thread.sleep(300); //停300ms,方便观察异步线程
} catch (InterruptedException e) {
e.printStackTrace();
}
User user=userEvent.getUser();
log.info("{},监听到[添加新用户]事件:{}",Thread.currentThread().getName(),user.toString());
//去数据库查询出user并执行多个任务:发邮件、送体验卡..
bussinessOperate(getUserByUserName(user.getUserName());
}
void bussinessOperate(User user){}
}
//启动类
@EnableAsync //开启对异步任务的支持,开启@EnableAsync之后@Async才能使用
@SpringBootApplication
public class DemoTestApplication {
public static void main(String[] args) {
SpringApplication.run(DemoTestApplication.class, args);
}
}
//测试类
public class TestEvent extends BaseTest{
@Autowired
UserServiceImpl userService;
@Test
public void test(){
userService.addUser();
}
}
//测试基础类
@Slf4j
@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class BaseTest {
@Before
public void before(){
log.info("单元测试before...");
}
@After
public void after(){
log.info("单元测试after...");
}
}
运行后结果:
@TransactionalEventListener型发布与监听
虽然上面@EventListener型解决了单机下多任务的发布监听,但是上面"事件发布"后如果没有提交当前事务,则"事件监听"就去数据库里查询user并执行多个任务,user不存在会报空指针,解决方法是用@TransactionalEventListener保证在"事件发布"后提交了当前事务,才会去执行“事件监听”
//除了事件监听类有点不同,其他代码均与上面一致,事件监听类:
@Component
@Slf4j
public class UserListerner {
//@EventListener //单纯监听UserEvent类事件
@Async //@Async可以开启一个异步任务(启动类要@EnableAsync),因为监听默认是同步的:监听到UserEvent类事件后,执行下面的代码,然后返回原链路继续执行原来的代码
@TransactionalEventListener(phase= TransactionPhase.AFTER_COMMIT,fallbackExecution = true) //phase默认为TransactionPhase.AFTER_COMMIT,它指定了在事件发布的相关事务提交后才会去执行以下监听方法;fallbackExecution默认为false,指如果"事件发布"不存在事务,则不会执行监听方法,如果为true则不管“事件发布”有没有事务,都会执行以下监听方法
public void afterAddUser(UserEvent userEvent){
try {
Thread.sleep(300);
} catch (InterruptedException e) {
e.printStackTrace();
}
User user=userEvent.getUser();
log.info("{},监听到[添加新用户]事件:{}",Thread.currentThread().getName(),user.toString());
//业务操作:发邮件、送体验卡...
bussinessOperate();
}
void bussinessOperate(){}
}
OK,如果文章哪里有错误或不足,欢迎各位留言。
创作不易,各位的「三连」是二少创作的最大动力!我们下期见!
spring中的事件发布与监听的更多相关文章
- JavaEE开发之Spring中的事件发送与监听以及使用@Profile进行环境切换
本篇博客我们就来聊一下Spring框架中的观察者模式的应用,即事件的发送与监听机制.之前我们已经剖析过观察者模式的具体实现,以及使用Swift3.0自定义过通知机制.所以本篇博客对于事件发送与监听的底 ...
- spring 自定义事件发布及监听(简单实例)
前言: Spring的AppilcaitionContext能够发布事件和注册相对应的事件监听器,因此,它有一套完整的事件发布和监听机制. 流程分析: 在一个完整的事件体系中,除了事件和监听器以外,还 ...
- Spring知识点回顾(07)事件发布和监听
Spring知识点回顾(07)事件发布和监听 1.DemoEvent extends ApplicationEvent { public DemoEvent(Object source, String ...
- SpringBoot系列——事件发布与监听
前言 日常开发中,我们经常会碰到这样的业务场景:用户注册,注册成功后需要发送邮箱.短信提示用户,通常我们都是这样写: /** * 用户注册 */ @GetMapping("/userRegi ...
- Spring事件发布与监听机制
我是陈皮,一个在互联网 Coding 的 ITer,微信搜索「陈皮的JavaLib」第一时间阅读最新文章,回复[资料],即可获得我精心整理的技术资料,电子书籍,一线大厂面试资料和优秀简历模板. 目录 ...
- SpringBoot | 第三十二章:事件的发布和监听
前言 今天去官网查看spring boot资料时,在特性中看见了系统的事件及监听章节.想想,spring的事件应该是在3.x版本就发布的功能了,并越来越完善,其为bean和bean之间的消息通信提供了 ...
- 关于JAVA中事件分发和监听机制实现的代码实例-绝对原创实用
http://blog.csdn.net/5iasp/article/details/37054171 文章标题:关于JAVA中事件分发和监听机制实现的代码实例 文章地址: http://blog.c ...
- Android中Button的五种监听事件
简单聊一下Android中Button的五种监听事件: 1.在布局文件中为button添加onClick属性,Activity实现其方法2.匿名内部类作为事件监听器类3.内部类作为监听器4.Activ ...
- 三种方式实现观察者模式 及 Spring中的事件编程模型
观察者模式可以说是众多设计模式中,最容易理解的设计模式之一了,观察者模式在Spring中也随处可见,面试的时候,面试官可能会问,嘿,你既然读过Spring源码,那你说说Spring中运用的设计模式吧, ...
随机推荐
- java常见面试问题总结
JDK1.7 并发的HashMap为什么会引起死循环? hashmap如何解决hash冲突,为什么hashmap中的链表需要转成红黑树? hashmap什么时候会触发扩容? jdk1.8之前并发操作h ...
- MyBatis 与 Hibernate 有哪些不同?
1.Mybatis 和 hibernate 不同,它不完全是一个 ORM 框架,因为 MyBatis 需要 程序员自己编写 Sql 语句. 2.Mybatis 直接编写原生态 sql,可以严格控制 s ...
- producer内存管理分析
1 概述 kafka producer调用RecordAccumulator#append来将消息存到本地内存.消息以TopicPartition为key分组存放,每个TopicPartition对应 ...
- 为什么要使用 rabbitmq?
1.在分布式系统下具备异步,削峰,负载均衡等一系列高级功能; 2.拥有持久化的机制,进程消息,队列中的信息也可以保存下来. 3.实现消费者和生产者之间的解耦. 4.对于高并发场景下,利用消息队列可以使 ...
- C++11最常用的新特性如下
1.auto关键字:编译器可以根据初始值自动推导出类型.但是不能用于函数传参.定义数组以及非静态成员变量. 2.nullptr关键字:是一种特殊类型的字面值,它可以被转换成任意其它类型的指针:而NUL ...
- su 和 sudo的区别
su是一个命令,可切换其他用户进行操作:而 '-' 号则是代表是否完全切换指定的用户环境信息 sudo是一个服务,可通过/etc/sudoers进行配置文件,让被限制的用户只能执行被授予的命令操作.
- centos 7环境下安装部署zookeeper
近一直在看zookeeper的知识,有所收获,打算写些一些关于zookeeper的博客,也当做是自己的复习和笔记. 在上一篇 博客中简单地介绍了centos 7 下如何安装jdk,这一篇将介绍如何在c ...
- 联想电脑“此主机支持 Intel VT-x,但 Intel VT-x 处于禁用状态” 解决方法
当在虚拟机上安装Ubuntu系统时,出现 "此主机支持 Intel VT-x,但 Intel VT-x 处于禁用状态" 弹窗此时需要进入BIOS修改相关的设置,此处以联想ideap ...
- 【uniapp 开发】uni-app 技术点的链接记录
优雅的H5下拉刷新.零依赖,高性能,多主题,易拓展 https://ask.dcloud.net.cn/article/12772 图像(头像)选择,截取,压缩,上传的分享 https://ask.d ...
- CCF201903-2二十四点
思路描述:最开始的思路是拿一个栈来存储数据和符号,在动手实践的过程中发现行不通,单个数字的char和int转换可以,但是加起来的数据两位数字就很难处理了. 然后就去看了看别人的思路,给了我一个很好的启 ...