多数据源事务——@DSTransactional注解原理

1.前言

在前面的文章中,提到一种手动提交多数据源事务的实现方式,dynamic-datasource包为我们提供了一种更为优雅,开箱即用的注解,即@DSTransactional,因为spring提供的@Tansactional注解是不支持多数据源的,@DSTransactional注解的出现刚好可以很好的弥补这一点。@DS注解和@DSTransactional注解是可以同时使用的,并且两者也是有着密不可分的联系,关于@DS注解请看我上一篇文章分析:动态数据源切换——@DS注解源码解析

2.@DSTransactional注解原理

1)在前文@DS注解的讨论中,不难发现DynamicDataSourceAopConfiguration类中还注册了一个advisor,就是@DSTransactional注解的切面:

image-20240116193722752

2)再看DynamicLocalTransactionInterceptor类,具体的事务开启和执行提交回滚放到了LocalTxUtil类中

image-20240120125636722

3)跟随LocalTxUtil类,将xid存入ThreadLocal类型的holder中实现开启本地事务,在拦截器的invoke方法中也会校验holder中是否为空,如果已经存在事务id,就直接执行目标方法;

image-20240120114856091

4)TransactionContext类:

image-20240120115542058

5)提交和回滚由ConnectionFactory类实现:ConnectionFactory中定义了CONNECTION_HOLDER存放数据源名称和ConnectionProxy的对应关系,而ConnectionProxy才是真正实现提交和回滚的类。

image-20240120115852431

image-20240120120300678

而putConnection方法是在执行AbstractRoutingDataSource#getConnection时被调用:

image-20240120120855491

6)ConnectionProxyConnection接口的实现类,ConnectionProxy的成员变量很简单只有数据源名称和Connection对象,要做的事情也很简单就是提交和回滚,在其实现上用notify方法代替,并没有实现Connection类的commit、rollback;默认设置提交方式为手动提交

image-20240120121311318

image-20240120124825898

3.总结

根据前文的分析,在执行AbstractRoutingDataSource#getConnection时,如果没有将数据源加入到ConnectionFactory,则会先切换数据源,再创建ConnectionProxy并将其加入ConnectionFactory:

image-20240120123432387

在开启多数据源事务时,先判断是否存在本地事务,是的话加入,即直接执行目标方法(就是传播行为的REQUIRED),随后方法执行完成后,根据是否有异常将所有加入到ConnectionFactory的连接一起提交或回滚:

image-20240120125838317

本博客内容仅供个人学习使用,禁止用于商业用途。转载需注明出处并链接至原文。

posted @ 2024-01-20 13:03  爱吃麦辣鸡翅  阅读(2852)  评论(0编辑  收藏  举报