30 张图带你分析:spring 事务源码,mysql 基础教程视频


ProxyTransactionManagementConfiguration.transactionAdvisor()注入事务切面


==========================================================================
实际运行入口之一(还有 cglib):JdkDynamicAopProxy…invoke()


ReflectiveMethodInvocation.proceed()切面调用链处理核心方法

TransactionInterceptor.invoke()从这里触发事务拦截

TransactionAspectSupport.invokeWithinTransaction()实现 Spring 事务的核心业务

TransactionAspectSupport.determineTransactionManager()定义指定的事务管理器

对于事务管理器,默认使用 DataSourceTransactionManager(可配置数据源的事务管理器),也可自定义事务管理器,然后配置数据源即可。
createTransactionIfNecessary()创建事务信息 TransactionInfo:其中包括数据源、事务连接(ConnectionHolder)、事务状态、连接缓存等;


DataSourceTransactionManager.doGetTransaction()获取事务对象:里面包含连接包装和缓存

TransactionSynchronizationManager.getResource()连接线程级缓存:确保当前线程拿到唯一的数据连接


AbstractPlatformTransactionManager.sta
rtTransaction()开启一个新事务

只有 newTransaction 为 true 时,spring 才会做实际的提交或回滚,这里是一个很重要的点。很多嵌套事务的坑,都是这里没有理解清楚。
DataSourceTransactionManager.doBegin()开启事务核心源码

TransactionSynchronizationManager.bindResource()设置当前连接和数据源的线程级绑定

==========================================================================
对于非编程式事务而言,Spring 事务的核心实现其实就是用 try / catch 包裹事务提交和回滚的范式而已,但提交和回滚里面的包装大有讲究。
TransactionAspectSupport.completeTransactionAfterThrowing()事务回滚实现


以上截图中 doSetRollbackOnly(),不会在连接上实际设置回滚点,只打个标记(当前事务需要回滚, commit 时会使用该标记)!
==========================================================================
AbstractPlatformTransactionManager.commit()事务实际提交源码这里



cleanupAfterCompletion()回收连接或恢复事务,这个点耐人寻味:当事务传播属性为 Require_New 时,会暂时挂起之前的连接,然后创建新连接;当新连接提交或回滚后,通过这个方法恢复之前连接和状态!!!!



OK 事务到这里,我根据源码分享一些关于嵌套子事务的甜点:
嵌套事务过程,中间有任何异常,只要没被屏蔽,则都会上抛,不会再执行后续代码;
只要设置 Require_New 事务传播属性,则每个 Transactional 注解方法内部都会单独提交或回滚;
嵌套事务会在除首个 Transactional 注解外的子事务中创建 savepoint 回滚点;
设置 savepoint 回滚点后,回滚时会回滚包括当前方法之前的所有事务;若只需回滚当前方法,则在最外层事务方法加 try{}catch(){//不抛出异常};
评论