项目概况

事务回滚原理

2026-01-292 min read未分类
源码分析

在前文单测类注入中我们知道.JUnit提供了一些监听器,允许 当单测方法执行时候去对单测上下文进行调整。所以呢事务回滚也是基于 这里的特性完成的。基于SpringBoot 2.1.x版本分析

源码分析

Spring中为了适配不通的数据库,提供了事务平台的概念。 PlatformTransactionManager 只要实现了该接口 就允许对事务进行控制。具体事务的控制是通过工具类来处理的。 TransactionContextHolder 可以获取当前线程 执行的事务上下文。JUnit通过该工具拿到事务的上下文,然后对此做响应的修改。具体的 修改逻辑见下文注释。两句话解释清楚。

TransactionalTestExecutionListener

伪代码分析

java
1 // 单测方法执行前,移除容器原来的事务管理器,然后开启一个新的事务 2 @Override 3 public void beforeTestMethod(final TestContext testContext) throws Exception { 4 Method testMethod = testContext.getTestMethod(); 5 Class<?> testClass = testContext.getTestClass(); 6 Assert.notNull(testMethod, "Test method of supplied TestContext must not be null"); 7 8 TransactionContext txContext = TransactionContextHolder.removeCurrentTransactionContext(); 9 Assert.state(txContext == null, "Cannot start new transaction without ending existing transaction"); 10 11 PlatformTransactionManager tm = null; 12 TransactionAttribute transactionAttribute = this.attributeSource.getTransactionAttribute(testMethod, testClass); 13 14 if (transactionAttribute != null) { 15 transactionAttribute = TestContextTransactionUtils.createDelegatingTransactionAttribute(testContext, 16 transactionAttribute); 17 18 if (logger.isDebugEnabled()) { 19 logger.debug("Explicit transaction definition [" + transactionAttribute + 20 "] found for test context " + testContext); 21 } 22 23 if (transactionAttribute.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NOT_SUPPORTED) { 24 return; 25 } 26 27 tm = getTransactionManager(testContext, transactionAttribute.getQualifier()); 28 Assert.state(tm != null, 29 () -> "Failed to retrieve PlatformTransactionManager for @Transactional test: " + testContext); 30 } 31 32 if (tm != null) { 33 txContext = new TransactionContext(testContext, tm, transactionAttribute, isRollback(testContext)); 34 runBeforeTransactionMethods(testContext); 35 txContext.startTransaction(); 36 TransactionContextHolder.setCurrentTransactionContext(txContext); 37 } 38 } 39 40 // 单测方法执行结束后,结束事务然后回滚或提交 41 @Override 42 public void afterTestMethod(TestContext testContext) throws Exception { 43 Method testMethod = testContext.getTestMethod(); 44 Assert.notNull(testMethod, "The test method of the supplied TestContext must not be null"); 45 46 TransactionContext txContext = TransactionContextHolder.removeCurrentTransactionContext(); 47 // If there was (or perhaps still is) a transaction... 48 if (txContext != null) { 49 TransactionStatus transactionStatus = txContext.getTransactionStatus(); 50 try { 51 // If the transaction is still active... 52 if (transactionStatus != null && !transactionStatus.isCompleted()) { 53 txContext.endTransaction(); 54 } 55 } 56 finally { 57 runAfterTransactionMethods(testContext); 58 } 59 } 60 }