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

调用 TransactionSynchronization#beforeCompletion 方法,由 Spring 事务托管,不是真的关闭连接,从 ThreadLocal 中删除 DataSource 和 ConnectionHolder 的映射关系;例如在 Mybatis-Spring 中的 SqlSessionSynchronization 中,会从 ThreadLocal 中删除 SqlSessionFactory 和 SqlSessionHolder 的映射关系,且调用其 SqlSession#close() 方法

标记三个前置操作已完成

如果有保存点,即嵌套事务,则调用 Connection#releaseSavepoint(Savepoint) 方法释放保存点,等外层的事务进行提交

否则,如果是一个新的事务,根据之前一直提到的 newTransaction 属性进行判断是否是一个新的事务

提交事务,执行 Connection#commit() 方法

// DataSourceTransactionManager.java @Override protected void doCommit(DefaultTransactionStatus status) { DataSourceTransactionObject txObject = (DataSourceTransactionObject) status.getTransaction(); Connection con = txObject.getConnectionHolder().getConnection(); if (status.isDebug()) { logger.debug("Committing JDBC transaction on Connection [" + con + "]"); } try { con.commit(); } catch (SQLException ex) { throw new TransactionSystemException("Could not commit JDBC transaction", ex); } }

否则,在事务被标记为全局回滚的情况下是否提前失败(默认为 false)

触发提交后的回调,调用 TransactionSynchronization#afterCommit 方法,JMS 会有相关操作,暂时忽略

触发完成后的回调,事务同步状态为已提交,调用 TransactionSynchronization#afterCompletion 方法,例如在 Mybatis-Spring 中的 SqlSessionSynchronization 中,会从 ThreadLocal 中删除 SqlSessionFactory 和 SqlSessionHolder 的映射关系,且调用其 SqlSession#close() 方法,解决可能出现的跨线程的情况

在完成后清理,清理相关资源,“释放”连接,唤醒被挂起的资源,如下:

// AbstractPlatformTransactionManager.java private void cleanupAfterCompletion(DefaultTransactionStatus status) { // <1> 设置为已完成 status.setCompleted(); // <2> 如果是一个新的事务同步器 if (status.isNewSynchronization()) { // 清理事务管理器中的 ThreadLocal 相关资源,包括事务同步器、事务名称、只读属性、隔离级别、真实的事务激活状态 TransactionSynchronizationManager.clear(); } // <3> 如果是一个新的事务 if (status.isNewTransaction()) { // 清理 Connection 资源,例如释放 Connection 连接,将其引用计数减一(不会真的关闭) // 如果这个 `con` 是中途创建的,和 ThreadLocal 中的不一致,则需要关闭 doCleanupAfterCompletion(status.getTransaction()); } // <4> 如果之前有被挂起的事务,则唤醒 if (status.getSuspendedResources() != null) { Object transaction = (status.hasTransaction() ? status.getTransaction() : null); // 唤醒被挂起的事务和资源,重新将 DataSource 和 ConnectionHolder 的映射绑定到 ThreadLocal 中 // 将之前挂起的相关属性重新设置到 ThreadLocal 中 resume(transaction, (SuspendedResourcesHolder) status.getSuspendedResources()); } }

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

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