一、执行入口
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。![](/i/l/?n=23&i=blog/1680081/202301/1680081-20230103203302335-538218270.png)
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](/i/l/?n=23&i=blog/1680081/202301/1680081-20230103204511759-1033237525.png)
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](/i/l/?n=23&i=blog/1680081/202301/1680081-20230103204809526-889990600.png)
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 }