死磕Spring之AOP篇 - Spring 事务详解 (14)

挂起事务,也就是从 ThreadLocal 中移除,并返回挂起的 ConnectionHolder 对象

// DataSourceTransactionManager.java @Override protected Object doSuspend(Object transaction) { DataSourceTransactionObject txObject = (DataSourceTransactionObject) transaction; // 将 Connection 连接持有者置空 txObject.setConnectionHolder(null); // 将 ThreadLocal 中的 DataSource 移除 return TransactionSynchronizationManager.unbindResource(obtainDataSource()); }

解除绑定当前事务各种属性,名称、只读、隔离级别、是否是真实的事务

返回被挂起的资源对象(对上面被挂起的对象进行封装)

否则,如果当前数据源事务对象不为空,则挂起

挂起事务,和 1.2 步相同

返回被挂起的资源对象(对上面被挂起的对象进行封装)

否则,什么都不用做,返回一个空对象

可以看到,挂起当前事务就是从 ThreadLocal 中移除相关资源,会将这些资源封装成一个对象返回,因为后续需要唤醒这些被挂起的资源(重新设置到 ThreadLocal 中)

小节

Spring 创建事务的过程主要分为两种情况,当前线程不处于一个事务中和正处于一个事务中,两种情况都需要根据事务的传播级别来做出不同的处理。创建一个事务的核心就是调用 Connection#setAutocommit(false) 方法,将自动提交关闭,这样一来,就可以在一个事务中根据行为作出相应的操作,例如出现异常进行回滚,没有问题则进行提交

当前线程不处于一个事务中:

如果是MANDATORY传播级别,则抛出异常

否则,如果是 REQUIRED | REQUIRES_NEW | NESTED 传播级别,则“创建”一个事务,将数据库的 commit 设置为 false,此时会设置事务状态里面的 newTransaction 属性 true,表示是一个新的事务

否则,创建一个“空”的事务状态对象,也就是不使用事务

当前线程正处于一个事务中:

如果是NEVER传播级别,则抛出异常

否则,如果是NOT_SUPPORTED传播级别,则将当前事务挂起,然后创建一个“空”的事务状态对象,也就是不使用事务

否则,如果是REQUIRES_NEW 传播级别,则将当前事务挂起,然后“创建”一个事务,将数据库的 commit 设置为 false,此时会设置事务状态里面的 newTransaction 属性 true,表示是一个新的事务;同时还保存了被挂起的事务相关资源,在本次事务结束后会唤醒它

否则,如果是 NESTED 传播级别,则沿用当前事务,就是设置事务状态里面的 newTransaction 属性 false,表示不是一个新的事务,不过会调用 Connection#setSavepoint(String) 方法创建一个 SAVEPOINT 保存点,相当于嵌套事务

否则,就是 SUPPORTS | REQUIRED 传播级别,沿用当前事务,就是设置事务状态里面的 newTransaction 属性 false,表示不是一个新的事务

注意到 DefaultTransactionStatus 事务状态对象有一个 newTransaction 属性,通过它可以知道是否是一个新的事务,在后续的 commit 和 rollback 有着关键的作用

至此,关于 Spring 创建事务的内容差不多就结束了,接下来我们来看看 Spring 是如何提交一个事务的

2. 提交事务

在 TransactionInterceptor 事务拦截处理过程中,如果方法的执行过程没有抛出异常,那么此时我们是不是需要调用 Connection#commit() 方法,提交本次事务,我们一起来看看 Spring 的处理过程

// TransactionAspectSupport.java protected void commitTransactionAfterReturning(@Nullable TransactionInfo txInfo) { if (txInfo != null && txInfo.getTransactionStatus() != null) { // 通过 DataSourceTransactionManager 提交当前事务 txInfo.getTransactionManager().commit(txInfo.getTransactionStatus()); } }

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/zygsff.html