来源:https://my.oschina.net/zhangxufeng/blog/1976076

前面我们讲到了Spring在进行事务逻辑织入的时候,无论是事务开始,提交或者回滚,都会触发相应的事务事件。本文首先会使用实例进行讲解Spring事务事件是如何使用的,然后会讲解这种使用方式的实现原理。

1. 示例

对于事务事件,Spring提供了一个注解@TransactionEventListener,将这个注解标注在某个方法上,那么就将这个方法声明为了一个事务事件处理器,而具体的事件类型则是由TransactionalEventListener.phase属性进行定义的。如下是TransactionalEventListener的声明:

关于这里的classes属性需要说明一下,如果指定了classes属性,那么当前监听方法的参数类型就可以直接使用所发布的事件的参数类型,如果没有指定,那么这里监听的参数类型可以使用两种:ApplicationEvent和PayloadApplicationEvent。对于ApplicationEvent类型的参数,可以通过其getSource()方法获取发布的事件参数,只不过其返回值是一个Object类型的,如果想获取具体的类型还需要进行强转;

对于PayloadApplicationEvent类型,其可以指定一个泛型参数,该泛型参数必须与发布的事件的参数类型一致,这样就可以通过其getPayload()方法获取事务事件发布的数据了。关于上述属性中的TransactionPhase,其可以取如下几个类型的值:

这里我们假设数据库有一个user表,对应的有一个UserService和User的model,用于往该表中插入数据,并且插入动作时使用注解标注目标方法。如下是这几个类的声明:

上述代码中有一点需要注意的是,对于需要监控事务事件的方法,在目标方法执行的时候需要使用ApplicationEventPublisher发布相应的事件消息。如下是对上述消息进行监控的程序:

这里对于事件的监控,只需要在监听方法上添加@TransactionalEventListener注解即可。这里需要注意的一个问题,在实际使用过程中,对于监听的事务事件,需要使用其他的参数进行事件的过滤,因为这里的监听还是会监听所有事件参数为User类型的事务,而无论其是哪个位置发出来的。如果需要对事件进行过滤,这里可以封装一个UserEvent对象,其内保存一个类似EventType的属性和一个User对象,这样在发布消息的时候就可以指定EventType属性,而在监听消息的时候判断当前方法监听的事件对象的EventType是否为目标type,如果是,则对其进行处理,否则直接略过。下面是上述程序的xml文件配置和驱动程序:

运行上述程序,其执行结果如下:

可以看到,这里确实成功监听了目标程序的相关事务行为。

2. 实现原理

关于事务的实现原理,这里其实是比较简单的,在前面的文章中,我们讲解到,Spring对事务监控的处理逻辑在TransactionSynchronization中,如下是该接口的声明:

很明显,这里的TransactionSynchronization接口只是抽象了一些行为,用于事务事件发生时触发,这些行为在Spring事务中提供了内在支持,即在相应的事务事件时,其会获取当前所有注册的TransactionSynchronization对象,然后调用其相应的方法。那么这里TransactionSynchronization对象的注册点对于我们了解事务事件触发有至关重要的作用了。这里我们首先回到事务标签的解析处,在前面讲解事务标签解析时,我们讲到Spring会注册一个TransactionalEventListenerFactory类型的bean到Spring容器中,这里关于标签的解析读者可以阅读本人前面的文章Spring事务用法示例与实现原理。这里注册的TransactionalEventListenerFactory实现了EventListenerFactory接口,这个接口的主要作用是先判断目标方法是否是某个监听器的类型,然后为目标方法生成一个监听器,其会在某个bean初始化之后由Spring调用其方法用于生成监听器。如下是该类的实现:

这里关于事务事件监听的逻辑其实已经比较清楚了。ApplicationListenerMethodTransactionalAdapter本质上是实现了ApplicationListener接口的,也就是说,其是Spring的一个事件监听器,这也就是为什么进行事务处理时需要使用ApplicationEventPublisher.publish()方法发布一下当前事务的事件。

ApplicationListenerMethodTransactionalAdapter在监听到发布的事件之后会生成一个TransactionSynchronization对象,并且将该对象注册到当前事务逻辑中,如下是监听事务事件的处理逻辑:

这里需要说明的是,上述annotation属性就是在事务监听方法上解析的TransactionalEventListener注解中配置的属性。可以看到,对于事务事件的处理,这里创建了一个TransactionSynchronization对象,其实主要的处理逻辑就是在返回的这个对象中,而createTransactionSynchronization()方法内部只是创建了一个TransactionSynchronizationEventAdapter对象就返回了。这里我们直接看该对象的源码:

可以看到,对于事务事件的处理,最终都是委托给了ApplicationListenerMethodAdapter.processEvent()方法进行的。如下是该方法的源码:

对于事务事件的处理,总结而言,就是为每个事务事件监听方法创建了一个TransactionSynchronizationEventAdapter对象,通过该对象在发布事务事件的时候,会在当前线程中注册该对象,这样就可以保证每个线程每个监听器中只会对应一个TransactionSynchronizationEventAdapter对象。在Spring进行事务事件的时候会调用该对象对应的监听方法,从而达到对事务事件进行监听的目的。

3. 小结

本文首先对事务事件监听程序的使用方式进行了讲解,然后在源码层面讲解了Spring事务监听器是如何实现的。在Spring事务监听器使用过程中,需要注意的是要对当前接收到的事件类型进行判断,因为不同的事务可能会发布同样的消息对象过来。

扩展阅读

Spring框架简介

Spring 面试问题 TOP 50

轻松了解Spring中的控制反转和依赖注入

微信公众号:javafirst

扫码关注免费获取更多资源

Spring 事务事件监控及实现原理相关推荐

  1. Spring事务事件监控

    2019独角兽企业重金招聘Python工程师标准>>> 前面我们讲到了Spring在进行事务逻辑织入的时候,无论是事务开始,提交或者回滚,都会触发相应的事务事件.本文首先会使用实例进 ...

  2. Spring事务传递机制和实现原理

    Spring事务传递机制和实现原理 实现原理 在实行事务的类或者方法上面添加@Transactional注解 Spring利用AOP思想机制,在方法执行前开启事务,在执行完成之后检查方法是否异常,根据 ...

  3. Spring 事务用法示例与实现原理

    关于事务,简单来说,就是为了保证数据完整性而存在的一种工具,其主要有四大特性:原子性,一致性,隔离性和持久性.对于Spring事务,其最终还是在数据库层面实现的,而Spring只是以一种比较优雅的方式 ...

  4. spring事务-说说Propagation及其实现原理

    前言 spring目前已是java开发的一个事实标准,这得益于它的便利.功能齐全.容易上手等特性.在开发过程当中,操作DB是非常常见的操作,而涉及到db,就会涉及到事务.事务在平时的开发过程当中,就算 ...

  5. Spring 事务管理@transactional 的实现原理和使用

    转载自:http://tech.lede.com/2017/02/06/rd/server/SpringTransactional/ 本文主要讨论Spring声明式事务中使用注解@Transactio ...

  6. spring 事务的实现方式和原理_spring整合atomikos实现分布式事务

    前言 Atomikos 是一个为Java平台提供增值服务的并且开源类事务管理器,主要用于处理跨数据库事务,比如某个指令在A库和B库都有写操作,业务上要求A库和B库的写操作要具有原子性,这时候就可以用到 ...

  7. Spring事务管理 | 数据库连接池流程原理分析

  8. Spring Event事件发布机制

    使用Spring Event优雅实现业务需求. 文章目录 一. 什么是Spring Event 二. 为什么要用Spring Event 三. 使用Spring Event实现邮件发送 一. 什么是S ...

  9. Spring事务的那些坑,这里都给你总结好了!

    点击上方 好好学java ,选择 星标 公众号 重磅资讯.干货,第一时间送达 今日推荐:硬刚一周,3W字总结,一年的经验告诉你如何准备校招! 个人原创100W+访问量博客:点击前往,查看更多 作者:蚊 ...

最新文章

  1. 亚马逊专家揭秘:如何建立自动检测乳腺癌的深度学习模型
  2. 机器学习的数学基础 - 信息论
  3. pip 另一种安装方法:python setup.py install
  4. MySQL 使用 OR 条件导致索引失效
  5. 【转】java反射--注解
  6. ruby array_Ruby中带有示例的Array.keep_if方法
  7. MOSS2010 中“找不到位于xxxx的web应用程序”的解决办法
  8. java的mwcellarray_Java 数组
  9. 腾讯面试Android高级岗。居然被一个多线程基础面倒了?
  10. 安防蓝海带来亿万商机 汉王人脸通掀起产业风暴
  11. (附源码)小程序 平衡膳食小程序 毕业设计 250859
  12. LGA1155、LGA1156、LGA1366、LGA2011的CPU插槽对应的都是什么型号的CPU
  13. 推荐一个Web前端程序员必须要吃透的书籍!
  14. 新的开始之Win7、CentOS 6.4 双系统 硬盘安装
  15. ServletConfig FilterConfig作用
  16. windows 安装 IDES
  17. 远程计算机时能看吗,QQ远程控制对方电脑上的所有东西都能看见吗 – 手机爱问...
  18. 练手必备,20个Python实战项目含源代码
  19. 【计算机网络】网络通信协议
  20. vue列表左右箭头滑动 vue+typescript实现左右箭头翻页,类似轮播图效果

热门文章

  1. Android-节日短信送祝福(UI篇:1-主布局的基本实现)
  2. Meta-INF文件的创建
  3. CreateThread、_beginthreadex和AfxBeginThread 的区别
  4. RabbitMq第三种模型--fanout
  5. 将python对象序列化成php能读取的格式(即能反序列化到对象)
  6. springmvc 切面记录操作日志
  7. HibernateSessionFactory类解析
  8. 安卓使用emoji表情
  9. 什么情况下会发生full Gc?如何排查频繁发生full Gc的原因?
  10. iOS问题记录 - Xcode 14.3版本运行项目报错