Spring 事务源码(四):事务执行流程

一、执行入口

  Spring事务是通过AOP实现,在AOP源码(五):具体执行流程 - 责任链模式中提到AOP流程执行入口为CglibAopProxy#DynamicAdvisedInterceptor#intercept,事务的代理对象入口也是如此。

二、执行流程

  在事务源码(三):事务相关对象的创建中提到在事务的执行链中包含两个MethodInterceptor类型的对象,即ExposeInvocationInterceptor、TransactionInterceptor。TransactionInterceptor是事务相关的Advice,接下来我们看看在TransactionInterceptor中是如何对事务做处理的。

2.1、概览

1、核心流程图

2、核心伪代码

  TransactionAspectSupport#invokeWithinTransaction 事务处理核心伪代码
 1 // 通过事务调用
 2 protected Object invokeWithinTransaction(Method method, @Nullable Class<?> targetClass,
 3       final InvocationCallback invocation) throws Throwable {
 4 
 5    // 获取事务属性源对象
 6    TransactionAttributeSource tas = getTransactionAttributeSource();
 7    // 通过事务属性源对象获取到当前方法的事务属性信息
 8    final TransactionAttribute txAttr = (tas != null ? tas.getTransactionAttribute(method, targetClass) : null);
 9    // 获取配置的事务管理器对象DataSourceTransactionManager
10    final TransactionManager tm = determineTransactionManager(txAttr);
11 
12    // TransactionManager 转换为  PlatformTransactionManager
13    PlatformTransactionManager ptm = asPlatformTransactionManager(tm);
14    // 获取连接点的唯一标识  类名+方法名
15    final String joinpointIdentification = methodIdentification(method, targetClass, txAttr);
16 
17    // 创建事务信息TransactionInfo
18    TransactionInfo txInfo = createTransactionIfNecessary(ptm, txAttr, joinpointIdentification);
19     
20    Object retVal;
21    try {
22         // 执行被增强方法,调用具体的处理逻辑
23         retVal = invocation.proceedWithInvocation();
24    }
25    catch (Throwable ex) {
26         // 异常回滚
27         completeTransactionAfterThrowing(txInfo, ex);
28         throw ex;
29     }
30    finally {
31         //清除事务信息,恢复线程私有的老的事务信息
32         cleanupTransactionInfo(txInfo);
33    }
34     
35     // 成功后提交,会进行资源储量,连接释放,恢复挂起事务等操作
36     commitTransactionAfterReturning(txInfo);
37     return retVal;
38     
39 }

  1、 getTransactionAttributeSource() 获取事务属性源对象,获取的是在IOC容器启动过程中,创建的NameMatchTransactionAttributeSource对象,内含属性nameMap,可通过方法名称获取方法对应的事务属性。

1 // key: 方法名称;value:方法的事务属性
2 private Map<String, TransactionAttribute> nameMap = new HashMap<>();

  2、determineTransactionManager(txAttr) 获取事务管理器,返回在IOC容器启动过程中,创建的DataSourceTransactionManager事务管理器对象。

  3、asPlatformTransactionManager(txAttr) 将DataSourceTransactionManager转换为PlatformTransactionManager。
 

  4、methodIdentification(method, targetClass, txAttr) 获取被增强方法的类名 + 方法名

  5、获取连接、开启事务 (包含事务传播特性的处理,执行insert、update、delete等被增强方法前的处理)

  6、执行被增强方法,数据库新增、删除、更新操作
  7、是否异常
   被增强方法执行异常,completeTransactionAfterThrowing(txInfo, ex) 事务回滚操作
   被增强方法执行无异常, commitTransactionAfterReturning(txInfo) 事务提交操作

2.2、创建事务信息

  TransactionAspectSupport#createTransactionIfNecessary 获取连接、开启事务核心伪代码:

 1 protected TransactionInfo createTransactionIfNecessary(@Nullable PlatformTransactionManager tm,
 2       @Nullable TransactionAttribute txAttr, final String joinpointIdentification) {
 3 
 4    // If no name specified, apply method identification as transaction name.
 5    // 如果没有名称指定则使用方法唯一标识,并使用DelegatingTransactionAttribute封装txAttr
 6    if (txAttr != null && txAttr.getName() == null) {
 7       txAttr = new DelegatingTransactionAttribute(txAttr) {
 8          @Override
 9          public String getName() {
10             return joinpointIdentification;
11          }
12       };
13    }
14     
15    // 获取TransactionStatus事务状态信息,开启事务、获取jdbc连接
16    TransactionStatus status = tm.getTransaction(txAttr);
17      
18    // 根据指定的属性与status准备TransactionInfo,
19    return prepareTransactionInfo(tm, txAttr, joinpointIdentification, status);
20 }

1、封装事务属性对象

  用DelegatingTransactionAttribute对象封装事务属性对象TransactionAttribute,若事务属性对象的name属性为空,重写DelegatingTransactionAttribute的getName方法,将被增强方法的类名+方法名返回;

2、事务状态 - TransactionStatus

AbstractPlatformTransactionManager#getTransaction 获取事务状态信息核心伪代码

 1 public final TransactionStatus getTransaction(@Nullable TransactionDefinition definition)
 2       throws TransactionException {
 3 
 4    // 若不指定事务定义,则使用默认的事务定义StaticTransactionDefinition
 5    TransactionDefinition def = (definition != null ? definition : TransactionDefinition.withDefaults());
 6 
 7    // 获取数据源对象 DataSourceTransactionObject
 8    Object transaction = doGetTransaction();
 9 
10    // 若已存在事务,按已存在事务流程执行
11    if (isExistingTransaction(transaction)) {
12       return handleExistingTransaction(def, transaction, debugEnabled);
13    }
14 
15    // Mandatory支持当前事务,如果不存在就抛异常
16    if (def.getPropagationBehavior() == TransactionDefinition.PROPAGATION_MANDATORY) {
17       throw new IllegalTransactionStateException(
18             "No existing transaction found for transaction marked with propagation 'mandatory'");
19    }
20    // 事务不存在,创建新事务
21    else if (def.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRED ||
22          def.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRES_NEW ||
23          def.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NESTED) {
24       SuspendedResourcesHolder suspendedResources = suspend(null);
25      
26       try {
27          // 开启事务(获取连接、开启事务)
28          return startTransaction(def, transaction, debugEnabled, suspendedResources);
29       }
30       catch (RuntimeException | Error ex) {
31          resume(null, suspendedResources);
32          throw ex;
33       }
34    }
35    else {
36       // 创建一个空事务信息,用作事务同步
37       boolean newSynchronization = (getTransactionSynchronization() == SYNCHRONIZATION_ALWAYS);
38       return prepareTransactionStatus(def, null, true, newSynchronization, debugEnabled, null);
39    }
40 }
1、获取数据源事务对象DataSourceTransactionObject,含是否允许当前事务设置保存点、jdbc连接持有对象,此处有一个复用JDBC连接逻辑。
  TransactionSynchronizationManager.getResource(obtainDataSource()) 获取数据源对应的jdbc连接 核心伪代码
 1 private static Object doGetResource(Object actualKey) {
 2     // 获取线程私有事务资源 
 3     Map<Object, Object> map = resources.get();
 4     // 第一次创建事务,线程私有事务资源为空,后续创建,返回null
 5     if (map == null) {
 6         return null;
 7     }
 8     // 获取线程私有事务资源中数据源对应的jdbc连接
 9     Object value = map.get(actualKey);
10     // 如果value是ResourceHolder类型,并且已经解绑
11     if (value instanceof ResourceHolder && ((ResourceHolder) value).isVoid()) {
12         // 将该数据源从线程私有事务资源中的元素map里移除
13         map.remove(actualKey);
14         // 线程私有事务资源的map为空,清空线程私有事务资源
15 
16         if (map.isEmpty()) {
17             resources.remove();
18         }
19         // 返回null
20         value = null;
21     }
22     // 返回数据源对应的jdbc连接
23     return value;
24 }
2、isExistingTransaction(transaction) 若已存在事务,根据被增强方法的传播特性,判断是抛异常、新建事务、还是支持原有事务。
3、根据被增强方法的传播特性判断是抛异常、创建事务、按非事务方式执行。
  当然我们最关心的还是按照事务的方式来执行被增强方法,下面来看看被增强方法的事务是如何处理的。

2.1、开启事务

  AbstractPlatformTransactionManager#startTransaction 开启事务核心伪代码
 1 // 开启事务
 2 private TransactionStatus startTransaction(TransactionDefinition definition, Object transaction,
 3       boolean debugEnabled, @Nullable SuspendedResourcesHolder suspendedResources) {
 4 
 5    // 是否需要新同步
 6    boolean newSynchronization = (getTransactionSynchronization() != SYNCHRONIZATION_NEVER);
 7    // 创建新事务状态对象
 8    DefaultTransactionStatus status = newTransactionStatus(
 9          definition, transaction, true, newSynchronization, debugEnabled, suspendedResources);
10    // 获取连接、开启事务
11    doBegin(transaction, definition);
12    // 新同步事务的设置,针对于当前线程的设置
13    prepareSynchronization(status, definition);
14    return status;
15 }
1、获取事务是否需要同步标识
  用作后续prepareSynchronization对线程私有变量做初始化操作的判断;
2、创建事务状态对象
  AbstractPlatformTransactionManager#newTransactionStatus 创建事务状态对象
 1 // 创建事务状态对象
 2 protected DefaultTransactionStatus newTransactionStatus(TransactionDefinition definition, @Nullable Object transaction, boolean newTransaction,
 3       boolean newSynchronization, boolean debug, @Nullable Object suspendedResources) {
 4        
 5   // 重置同步标识,只有当前事务需要同步,并且未被激活,同步标识为true
 6   boolean actualNewSynchronization = newSynchronization && !TransactionSynchronizationManager.isSynchronizationActive();
 7    // 创建DefaultTransactionStatus事务状态对象
 8   return new DefaultTransactionStatus(transaction, newTransaction, actualNewSynchronization, definition.isReadOnly(), debug, suspendedResources);
 9 }
3、获取连接、开启事务
0
  
  DataSourceTransactionManager#doBegin 获取连接、开启事务核心伪代码:
 1 // 获取连接、开启事务
 2 protected void doBegin(Object transaction, TransactionDefinition definition) {
 3    // 强制转化事务对象
 4    DataSourceTransactionObject txObject = (DataSourceTransactionObject) transaction;
 5    Connection con = null;
 6 
 7    try {
 8       // 判断事务对象没有数据库连接持有器
 9       if (!txObject.hasConnectionHolder() ||
10             txObject.getConnectionHolder().isSynchronizedWithTransaction()) {
11          // 通过数据源获取一个数据库连接对象
12          Connection newCon = obtainDataSource().getConnection();
13 
14          // 把数据库连接包装成一个ConnectionHolder对象 然后设置到txObject对象中去
15          txObject.setConnectionHolder(new ConnectionHolder(newCon), true);
16       }
17 
18       // 标记当前的连接是一个同步事务
19       txObject.getConnectionHolder().setSynchronizedWithTransaction(true);
20       // 获取JDBC连接
21       con = txObject.getConnectionHolder().getConnection();
22 
23       // 为当前的事务设置隔离级别
24       Integer previousIsolationLevel = DataSourceUtils.prepareConnectionForTransaction(con, definition);
25       // 设置先前隔离级别
26       txObject.setPreviousIsolationLevel(previousIsolationLevel);
27       // 设置是否只读
28       txObject.setReadOnly(definition.isReadOnly());
29 
30       // 关闭自动提交
31       if (con.getAutoCommit()) {
32          //设置需要恢复自动提交
33          txObject.setMustRestoreAutoCommit(true);
34          // 关闭自动提交
35          con.setAutoCommit(false);
36       }
37 
38       // 判断是否设置为只读事务
39       prepareTransactionalConnection(con, definition);
40       // 标记激活事务
41       txObject.getConnectionHolder().setTransactionActive(true);
42 
43       // 设置事务超时时间
44       int timeout = determineTimeout(definition);
45       if (timeout != TransactionDefinition.TIMEOUT_DEFAULT) {
46          txObject.getConnectionHolder().setTimeoutInSeconds(timeout);
47       }
48 
49       // 绑定数据源和连接到同步管理器上,把数据源作为key,数据库连接作为value 设置到线程变量中
50       if (txObject.isNewConnectionHolder()) {
51          // 将当前获取到的连接绑定到当前线程
52          TransactionSynchronizationManager.bindResource(obtainDataSource(), txObject.getConnectionHolder());
53       }
54    }
55 
56    catch (Throwable ex) {
57       if (txObject.isNewConnectionHolder()) {
58          // 释放数据库连接
59          DataSourceUtils.releaseConnection(con, obtainDataSource());
60          txObject.setConnectionHolder(null, false);
61       }
62       throw new CannotCreateTransactionException("Could not open JDBC Connection for transaction", ex);
63    }
64 }
3.1、获取jdbc连接
  第一次创建事务,数据源属性对象中的数据库jdbc连接为空,通过数据源获取jdbc数据源连接。
3.2、填充数据源属性对象属性
  1、设置连接持有器中的事务为同步事务,设置数据源属性对象之前的隔离级别、设置只读属性;
  2、关闭jdbc连接的自动提交,开启事务;
  3、标记当前事务为激活状态,可用作后续prepareSynchronization对线程私有变量做初始化操作的判断;
3.3、绑定新的jdbc连接至当前线程的事务资源中
  若当前连接是一个新的jdbc连接,需要将当前jdbc连接绑定到线程当前线程私有的事务资源属性中TransactionSynchronizationManager#bindResource 核心伪代码如下:
 1 // 绑定jdbc连接至当前线程的事务资源中
 2 public static void bindResource(Object key, Object value) throws IllegalStateException {
 3    // 获取数据源
 4    Object actualKey = TransactionSynchronizationUtils.unwrapResourceIfNecessary(key);
 5    Assert.notNull(value, "Value must not be null");
 6    // 获取线程私有事务资源中jdbc连接
 7    Map<Object, Object> map = resources.get();
 8    // 第一次创建事务,事务资源未创建,初始化线程私有事务资源
 9    if (map == null) {
10       map = new HashMap<>();
11       resources.set(map);
12    }
13    // 将数据源作为key,jdbc连接作为value,绑定到线程私有的事务资源中
14    Object oldValue = map.put(actualKey, value);
15    
16    // 若当前线程的事务资源中原有的value为ResourceHolder类型,并且已经解绑,将原有的事务资源value置空
17    if (oldValue instanceof ResourceHolder && ((ResourceHolder) oldValue).isVoid()) {
18        oldValue = null;
19    }
20 
21    // 若当前线程的事务资源已经被绑定,抛异常
22    if (oldValue != null) {
23       throw new IllegalStateException("Already value [" + oldValue + "] for key [" +
24             actualKey + "] bound to thread [" + Thread.currentThread().getName() + "]");
25    }
26   
27 }
  当外层事务的传播特性为REQUIRED,内层的传播特性也为REQUIRED时,内层可复用外层创建的jdbc连接。通过数据源获取的jdbc连接是同一个。
4、初始化线程私有的事务信息
  AbstractPlatformTransactionManager#prepareSynchronization 核心伪代码:

 

 1 // 当前事务的名称
 2 private static final ThreadLocal<String> currentTransactionName =
 3       new NamedThreadLocal<>("Current transaction name");
 4 
 5 // 当前事务是否只读
 6 private static final ThreadLocal<Boolean> currentTransactionReadOnly =
 7       new NamedThreadLocal<>("Current transaction read-only status");
 8 
 9 // 当前事务的隔离级别
10 private static final ThreadLocal<Integer> currentTransactionIsolationLevel =
11       new NamedThreadLocal<>("Current transaction isolation level");
12 
13 // 实际事务是否激活
14 private static final ThreadLocal<Boolean> actualTransactionActive =
15       new NamedThreadLocal<>("Actual transaction active");
16 
17 // 初始化线程私有事务信息
18 protected void prepareSynchronization(DefaultTransactionStatus status, TransactionDefinition definition) {
19    if (status.isNewSynchronization()) {
20       // 绑定事务激活状态
21       TransactionSynchronizationManager.setActualTransactionActive(status.hasTransaction());
22       // 设置当前事务的隔离级别
23       TransactionSynchronizationManager.setCurrentTransactionIsolationLevel(
24             definition.getIsolationLevel() != TransactionDefinition.ISOLATION_DEFAULT ?
25                   definition.getIsolationLevel() : null);
26       // 设置是否为只读事务
27       TransactionSynchronizationManager.setCurrentTransactionReadOnly(definition.isReadOnly());
28       // 设置事务的名称
29       TransactionSynchronizationManager.setCurrentTransactionName(definition.getName());
30       TransactionSynchronizationManager.initSynchronization();
31    }
32 }

3、事务信息 - TransactionInfo

0
  
  事务信息准备核心伪代码:
 1 // 准备事务信息
 2 protected TransactionInfo prepareTransactionInfo(@Nullable PlatformTransactionManager tm,
 3   @Nullable TransactionAttribute txAttr, String joinpointIdentification,
 4     @Nullable TransactionStatus status) {
 5    
 6   // 创建事务信息
 7   TransactionInfo txInfo = new TransactionInfo(tm, txAttr, joinpointIdentification);
 8 
 9 
10 
11   // 设置新事务状态
12   txInfo.newTransactionStatus(status);
13   
14    // 事务信息绑定到当前线程
15   txInfo.bindToThread();
16   
17    // 返回事务信息
18   return txInfo;
19 }

3.1、创建事务信息

  创建TransactionInfo对象,封装事务管理器,事务注解属性,被增强方法类名+方法名,事务状态对象

3.2、事务信息绑定到当前线程

 1 // 持有当前被增强方法的事务状态,支持多个被增强方法间的事务处理
 2 private static final ThreadLocal<TransactionInfo> transactionInfoHolder =
 3       new NamedThreadLocal<>("Current aspect-driven transaction");
 4 
 5 // 将事务信息绑定到当前线程 
 6 private void bindToThread() {
 7     // 获取事务信息持有器原来的事务信息,并设置到oldTransactionInfo属性
 8     this.oldTransactionInfo = transactionInfoHolder.get();
 9     // 将当前线程的事务属性设置进事务持有器中
10     transactionInfoHolder.set(this);
11 }

2.3、事务提交

  TransactionAspectSupport#commitTransactionAfterReturning 调用事务管理器提交事务概览伪代码
1 // 提交事务
2 protected void commitTransactionAfterReturning(@Nullable TransactionInfo txInfo) {
3    // 事务信息不为空,并且事务信息对象持有事务状态不为空
4    if (txInfo != null && txInfo.getTransactionStatus() != null) {
5       // 调用事务信息对象中事务管理器的事务提交方法
6       txInfo.getTransactionManager().commit(txInfo.getTransactionStatus());
7    }
8 }

1、提交处理

  AbstractPlatformTransactionManager#commit 事务提交伪代码
1 public final void commit(TransactionStatus status) throws TransactionException {
2   // 获取事务状态对象  
3   DefaultTransactionStatus defStatus = (DefaultTransactionStatus) status;
4   // 处理事务提交
5   processCommit(defStatus);
6 }

  AbstractPlatformTransactionManager#processCommit 处理事务提交伪代码

 1 private void processCommit(DefaultTransactionStatus status) throws TransactionException {
 2    try {       
 3      //当前状态是新事务
 4      if (status.isNewTransaction()) {
 5         // 若当前事务为新事务,事务提交
 6         doCommit(status);
 7      }      
 8    } finally {
 9       //根据条件,完成后数据清除,和线程的私有资源解绑,重置连接自动提交,隔离级别,是否只读,释放连接,恢复挂起事务等
10       cleanupAfterCompletion(status);
11    }
12 }

1.1、事务提交

  DataSourceTransactionManager#doCommit 事务提交核心伪代码
 1 protected void doCommit(DefaultTransactionStatus status) {
 2     // 获取事务状态中的数据源事务对象
 3     DataSourceTransactionObject txObject = (DataSourceTransactionObject) status.getTransaction();
 4     // 获取数据源事务对象中连接持有器的jdbc连接
 5     Connection con = txObject.getConnectionHolder().getConnection();
 6     try {
 7         // jdbc连接事务提交
 8         con.commit();
 9     }
10 catch (SQLException ex) {
11         throw new TransactionSystemException("Could not commit JDBC transaction", ex);
12     }
13 }

1.2、提交完成时的清理

  AbstractPlatformTransactionManager#cleanupAfterCompletion 提交完成时的清理核心伪代码
private void cleanupAfterCompletion(DefaultTransactionStatus status) {
   // 将当前事务设置为完成状态
   status.setCompleted();
   // 新事务完成事务提交,清理线程私有事务属性资源
   if (status.isNewSynchronization()) {
      TransactionSynchronizationManager.clear();
   }
   // 恢复jdbc连接相关操作
   if (status.isNewTransaction()) {
      doCleanupAfterCompletion(status.getTransaction());
   }
   // 恢复挂起事务
   if (status.getSuspendedResources() != null) {
      Object transaction = (status.hasTransaction() ? status.getTransaction() : null);
      resume(transaction, (SuspendedResourcesHolder) status.getSuspendedResources());
   }
}
1、清理线程私有事务属性资源
  TransactionSynchronizationManager#clear() 清除当前线程私有的事务同步信息核心代码
 1 // 事务同步
 2 private static final ThreadLocal<Set<TransactionSynchronization>> synchronizations = new NamedThreadLocal<>("Transaction synchronizations");
 3 
 4 // 当前事务的名称
 5 private static final ThreadLocal<String> currentTransactionName = new NamedThreadLocal<>("Current transaction name");
 6 
 7 // 当前事务是否只读
 8 private static final ThreadLocal<Boolean> currentTransactionReadOnly = new NamedThreadLocal<>("Current transaction read-only status");
 9 
10 // 当前事务的隔离级别
11 private static final ThreadLocal<Integer> currentTransactionIsolationLevel = new NamedThreadLocal<>("Current transaction isolation level");
12 
13 // 实际事务是否激活
14 private static final ThreadLocal<Boolean> actualTransactionActive = new NamedThreadLocal<>("Actual transaction active");
15    
16    public static void clear() {
17        synchronizations.remove();
18        currentTransactionName.remove();
19        currentTransactionReadOnly.remove();
20        currentTransactionIsolationLevel.remove();
21        actualTransactionActive.remove();
22    }
2、恢复jdbc连接相关操作
  DataSourceTransactionManager#doCleanupAfterCompletion jdbc连接相关操作核心伪代码
 1 // 事务提交后jdbc连接相关处理
 2 protected void doCleanupAfterCompletion(Object transaction) {
 3    // 获取数据源事务对象
 4    DataSourceTransactionObject txObject = (DataSourceTransactionObject) transaction;
 5 
 6    // 新事务,将数据库连接从当前线程中解除绑定
 7    if (txObject.isNewConnectionHolder()) {
 8       TransactionSynchronizationManager.unbindResource(obtainDataSource());
 9    }
10 
11    // 获取连接
12    Connection con = txObject.getConnectionHolder().getConnection();
13    // 关闭事务,恢复数据库连接的自动提交属性
14    if (txObject.isMustRestoreAutoCommit()) {
15      con.setAutoCommit(true);
16    }
17    // 重置数据库jdbc连接, 恢复原有隔离级别、是否只读属性
18    DataSourceUtils.resetConnectionAfterTransaction(con, txObject.getPreviousIsolationLevel(), txObject.isReadOnly());
19 
20    // 当前事务是独立的新创建的事务,在事务完成时释放数据库连接并关闭连接
21    if (txObject.isNewConnectionHolder()) {     
22       DataSourceUtils.releaseConnection(con, this.dataSource);
23    }
24 
25    // 清除数据源事务对象中的连接持有器
26    txObject.getConnectionHolder().clear();
27 }

  jdbc连接解绑、属性恢复、连接释放、连接关闭及数据源事务对象持有jdbc连接释放操作。

3、恢复挂起事务
  AbstractPlatformTransactionManager#resume 恢复外层原挂起事务核心代码
 1 // 恢复外层挂起事务
 2 protected final void resume(@Nullable Object transaction, @Nullable SuspendedResourcesHolder resourcesHolder)
 3       throws TransactionException {
 4    // 若存在挂起事务,恢复挂起事务
 5    if (resourcesHolder != null) {
 6       // 获取挂起事务的资源属性
 7       Object suspendedResources = resourcesHolder.suspendedResources;
 8       // 挂起事务的资源属性不为空,将事务属性资源绑定到线程私有的事务属性资源中
 9       if (suspendedResources != null) {
10          doResume(transaction, suspendedResources);
11       }
12    }
13 }

2.3、事务回滚

  TransactionAspectSupport#completeTransactionAfterThrowing 事务回滚概览伪代码:
 1 // 异常时事务处理
 2 protected void completeTransactionAfterThrowing(@Nullable TransactionInfo txInfo, Throwable ex) {
 3    if (txInfo != null && txInfo.getTransactionStatus() != null) {
 4       // 事务信息中事务属性不为空,并且事务属性中回滚
 5       if (txInfo.transactionAttribute != null && txInfo.transactionAttribute.rollbackOn(ex)) {
 6         // 进行回滚
 7         txInfo.getTransactionManager().rollback(txInfo.getTransactionStatus());
 8       }
 9       else {
10          // 回滚标识rollBackOnly为 false,执行提交
11          txInfo.getTransactionManager().commit(txInfo.getTransactionStatus());
12       }
13    }
14 }

1、回滚标识判断

  DefaultTransactionAttribute#rollbackOn 是否回滚判断标识
1 // 未捕获异常的回滚操作
2 public boolean rollbackOn(Throwable ex) {
3    return (ex instanceof RuntimeException || ex instanceof Error);
4 }

2、回滚处理

  AbstractPlatformTransactionManager#processRollback 回滚核心伪代码
 1 // 处理回滚
 2 private void processRollback(DefaultTransactionStatus status, boolean unexpected) {
 3    try {        
 4       // 当前事务是一个新事务
 5       if (status.isNewTransaction()) {
 6         // 进行回滚
 7         doRollback(status);
 8       }
 9    }
10    finally {
11       // 回滚完成时的处理
12       cleanupAfterCompletion(status);
13    }
14 }

2.1、回滚处理

  DataSourceTransactionManager#doRollback 事务回滚核心伪代码
 1 @Override
 2 protected void doRollback(DefaultTransactionStatus status) {
 3    // 获取事务状态中的数据源事务对象
 4    DataSourceTransactionObject txObject = (DataSourceTransactionObject) status.getTransaction();
 5    // 获取数据源事务对象中连接持有器的jdbc连接
 6    Connection con = txObject.getConnectionHolder().getConnection();
 7    try {
 8       // jdbc的回滚
 9       con.rollback();
10    }catch (SQLException ex) {
11       throw new TransactionSystemException("Could not roll back JDBC transaction", ex);
12    }
13 }

2.2、回滚完成时的清理

  同事务提交完成时的清理操作。
posted @ 2023-01-03 21:01  无虑的小猪  阅读(352)  评论(0编辑  收藏  举报