Spring事务部分源码解析(二) - 事务管理器
按照上篇流程详解
获取方法的Transaction配置
按照上篇对于几个实体类的描述,可以发现注解@Transactional的属性的字段和TransactionDefinition大致比较相似,但又不完全一致.
从@Transactional开始讲起
这个显然很常见,就是我们平时需要事务时用到的注解.可是spring如何去解析?我们看一下使用到这个注解的地方,排除掉在test和comment下的使用.
进入方法
TransactionAttribute正是上篇文章中TransactionDefinition的子类
返回的RuleBasedTransactionAttribute我们看一下他的继承图
我们打开源码看一下RuleBasedTransactionAttribute和父类DefaultTransactionAttribute晚上寻找发现,事务常规的设置是继承DefaultTransactionDefinition来注入,rollback相关则实现TransactionAttribute.这就是我们上篇提到TransactionAttribute和TransactionDefinition责任的划分
我们网上追溯,调用方
AnnotationTransactionAttributeSource.findTransactionAttribute()
AbstractFallbackTransactionAttributeSource.computeTransactionAttribute
AnnotationTransactionAttributeSource.getTransactionAttribute()
TransactionAspectSupport.invokeWithinTransaction
获取Transaction配置流程:根据方法和类确定唯一key,从缓存中获取.如果获取不到则通过TransactionAnnotationParser解析方法来获取事务属性.并放置缓存中
获取事务管理器(PlatformTransactionManager)
接口定义方法(可以发现极其精简干净)
抽象子类AbstractPlatformTransactionManager, 可以发现多了很多方法.但并没有实现,用于子类继承处理
子类
我们可以关注一下DataSourceTransactionManager和RabbitTransactionManager,是抽象类的一个实现.DataSourceTransactionManager的具体实现是通过Java提供的接口实现.而RabbitTransactionManager则是自己实现(毕竟已经属于定制了)
1 |
|
AbstractPlatformTransactionManager.rollback()
大致说一下回滚流程.
- 触发TransactionSynchronization完成前事件
- 事务具体实现的真正回滚
- 触发TransactionSynchronization完成后事件
- 标记完成,执行后续清理操作
1 |
|
AbstractPlatformTransactionManager.commit()
从图中看出在某种情况会执行回滚操作.最开始看到这里的时候也迷过.后来在一次事务测试时,同一个事务,方法嵌套时,内部方法抛异常,但是外部方法捕获正常处理.一部分觉得内部回滚外部不回滚.实际结果是内外都会回滚和是否捕获并没有关系. 可以回顾一下processRollback()中的status.isLocalRollbackOnly() || isGlobalRollbackOnParticipationFailure()判断
1
private boolean globalRollbackOnParticipationFailure = true;
默认为true,也就是说在非特意设置的情况下会执行doSetRollbackOnly(status);将rollbackOnly设置为true.在也就是说当内部内部方法发生异常之后会上下文TransactionStatus.rollbackOnly为true,执行的便是processRollback().这也就解释为什么内部方法捕获之后依旧会回滚的原因/
1ps: 本身在同一个事务,内部方法发生异常执行回滚,理应是整个事务回滚而不是部分回滚.以为捕获异常处理之后再提交这种思想本身就不对噢!!!
如果没有发生异常.则执行正常提交流程
1 |
|
执行流程
- 执行预提交处理
- 触发提交前事件
- 触发完成事件
- 提交
- 触发提交事件
- 触发提交完成事件
- 清除状态
1 |
|
AbstractPlatformTransactionManager.cleanupAfterCompletion()
其实这里也没什聊的,打开方法的源码基本能发现都是清除上下文状态.也代表事务的结束
总结
- AbstractPlatformTransactionManager实现了核心的逻辑,每一个核心的逻辑的具体实现又留给各个厂商实现.这一部分挺像AbstractQueuedSynchronizer的.设计挺好的.扩展性好,具体的逻辑又帮你实现好.只需要继承定制实现自己非常简单的逻辑就好
- 事务嵌套情况通过线程上线文来处理
- 多事务通过触发事件处理(后续讲TransactionSynchronization会聊到),扩展性真的挺好
1 |
|