Spring Boot Transaction 源码解析(二)
目录
DataSourceTransactionManager
doGetTransaction
isExistingTransaction
doBegin
doCommit
doSuspend
doRollback
doCleanupAfterCompletion
DataSourceUtils
ConnectionSynchronization
suspend
JDBC事务时Spring 事务的具体实现。
DataSourceTransactionManager
public class DataSourceTransactionManager extends AbstractPlatformTransactionManagerimplements ResourceTransactionManager, InitializingBean {//数据库DataSourceprivate DataSource dataSource;private boolean enforceReadOnly = false;
}
doGetTransaction
构造DataSourceTransactionObject,存储ConnectionHolder 。
@Overrideprotected Object doGetTransaction() {DataSourceTransactionObject txObject = new DataSourceTransactionObject();txObject.setSavepointAllowed(isNestedTransactionAllowed());
//通过DataSource获取ConnectionHolder ConnectionHolder conHolder =(ConnectionHolder) TransactionSynchronizationManager.getResource(obtainDataSource());
//DataSourceTransactionObject设置ConnectionHolder txObject.setConnectionHolder(conHolder, false);return txObject;}
isExistingTransaction
如果存在getConnectionHolder,并且有活跃事务,则表示已存在事务。
@Overrideprotected boolean isExistingTransaction(Object transaction) {DataSourceTransactionObject txObject = (DataSourceTransactionObject) transaction;return (txObject.hasConnectionHolder() && txObject.getConnectionHolder().isTransactionActive());}
doBegin
主要功能就是保存Connection,设置事务状态。
@Overrideprotected void doBegin(Object transaction, TransactionDefinition definition) {//获取事务对象。DataSourceTransactionObject txObject = (DataSourceTransactionObject) transaction;Connection con = null;try {//如果没有ConnectionHolder,则构造一个。if (!txObject.hasConnectionHolder() ||txObject.getConnectionHolder().isSynchronizedWithTransaction()) {Connection newCon = obtainDataSource().getConnection();if (logger.isDebugEnabled()) {logger.debug("Acquired Connection [" + newCon + "] for JDBC transaction");}txObject.setConnectionHolder(new ConnectionHolder(newCon), true);}txObject.getConnectionHolder().setSynchronizedWithTransaction(true);//从事务对象获取Connectioncon = txObject.getConnectionHolder().getConnection();//事务准备,返回隔离级别,并设置到当前事务对象。Integer previousIsolationLevel = DataSourceUtils.prepareConnectionForTransaction(con, definition);txObject.setPreviousIsolationLevel(previousIsolationLevel);txObject.setReadOnly(definition.isReadOnly());// Switch to manual commit if necessary. This is very expensive in some JDBC drivers,// so we don't want to do it unnecessarily (for example if we've explicitly// configured the connection pool to set it already).//是否自动提交。如果是自动提交,则改为手动提交。if (con.getAutoCommit()) {txObject.setMustRestoreAutoCommit(true);if (logger.isDebugEnabled()) {logger.debug("Switching JDBC Connection [" + con + "] to manual commit");}con.setAutoCommit(false);}//准备提交。prepareTransactionalConnection(con, definition);//激活当前事务。txObject.getConnectionHolder().setTransactionActive(true);//设置超时。int timeout = determineTimeout(definition);if (timeout != TransactionDefinition.TIMEOUT_DEFAULT) {txObject.getConnectionHolder().setTimeoutInSeconds(timeout);}// 如果是新建的,则绑定到当前线程。if (txObject.isNewConnectionHolder()) {TransactionSynchronizationManager.bindResource(obtainDataSource(), txObject.getConnectionHolder());}}catch (Throwable ex) {if (txObject.isNewConnectionHolder()) {DataSourceUtils.releaseConnection(con, obtainDataSource());txObject.setConnectionHolder(null, false);}throw new CannotCreateTransactionException("Could not open JDBC Connection for transaction", ex);}}
doCommit
通过事务的Connection,调用commit方法,提交事务。
@Overrideprotected void doCommit(DefaultTransactionStatus status) {
//从事务对象中获取Connection,调用Connection的提交。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);}}
doSuspend
Connection设置为null,解绑资源
@Overrideprotected Object doSuspend(Object transaction) {DataSourceTransactionObject txObject = (DataSourceTransactionObject) transaction;txObject.setConnectionHolder(null);
//当前线程解绑资源,return TransactionSynchronizationManager.unbindResource(obtainDataSource());}@Overrideprotected void doResume(@Nullable Object transaction, Object suspendedResources) {
//重新绑定资源TransactionSynchronizationManager.bindResource(obtainDataSource(), suspendedResources);}
doRollback
调用Connection.rollback()方法回滚事务。
@Overrideprotected void doRollback(DefaultTransactionStatus status) {DataSourceTransactionObject txObject = (DataSourceTransactionObject) status.getTransaction();Connection con = txObject.getConnectionHolder().getConnection();if (status.isDebug()) {logger.debug("Rolling back JDBC transaction on Connection [" + con + "]");}try {con.rollback();}catch (SQLException ex) {throw new TransactionSystemException("Could not roll back JDBC transaction", ex);}}
doCleanupAfterCompletion
如果新事务,解绑资源。恢复状态:自动提交、connection。
@Overrideprotected void doCleanupAfterCompletion(Object transaction) {DataSourceTransactionObject txObject = (DataSourceTransactionObject) transaction;// Remove the connection holder from the thread, if exposed.if (txObject.isNewConnectionHolder()) {TransactionSynchronizationManager.unbindResource(obtainDataSource());}// Reset connection.Connection con = txObject.getConnectionHolder().getConnection();try {if (txObject.isMustRestoreAutoCommit()) {con.setAutoCommit(true);}DataSourceUtils.resetConnectionAfterTransaction(con, txObject.getPreviousIsolationLevel(), txObject.isReadOnly());}catch (Throwable ex) {logger.debug("Could not reset JDBC Connection after transaction", ex);}if (txObject.isNewConnectionHolder()) {if (logger.isDebugEnabled()) {logger.debug("Releasing JDBC Connection [" + con + "] after transaction");}DataSourceUtils.releaseConnection(con, this.dataSource);}txObject.getConnectionHolder().clear();}
DataSourceUtils
DataSourceUtils,工具类,用于辅助DataSource操作。主要就是Connection相关操作,
ConnectionSynchronization
用于事务同步。
private final ConnectionHolder connectionHolder;private final DataSource dataSource;private int order;private boolean holderActive = true;
suspend
解绑datasource资源,释放connection。
@Overridepublic void suspend() {if (this.holderActive) {TransactionSynchronizationManager.unbindResource(this.dataSource);if (this.connectionHolder.hasConnection() && !this.connectionHolder.isOpen()) {// Release Connection on suspend if the application doesn't keep// a handle to it anymore. We will fetch a fresh Connection if the// application accesses the ConnectionHolder again after resume,// assuming that it will participate in the same transaction.releaseConnection(this.connectionHolder.getConnection(), this.dataSource);this.connectionHolder.setConnection(null);}}}
@Overridepublic void resume() {if (this.holderActive) {TransactionSynchronizationManager.bindResource(this.dataSource, this.connectionHolder);}}
@Overridepublic void beforeCompletion() {// Release Connection early if the holder is not open anymore// (that is, not used by another resource like a Hibernate Session// that has its own cleanup via transaction synchronization),// to avoid issues with strict JTA implementations that expect// the close call before transaction completion.if (!this.connectionHolder.isOpen()) {TransactionSynchronizationManager.unbindResource(this.dataSource);this.holderActive = false;if (this.connectionHolder.hasConnection()) {releaseConnection(this.connectionHolder.getConnection(), this.dataSource);}}}@Overridepublic void afterCompletion(int status) {// If we haven't closed the Connection in beforeCompletion,// close it now. The holder might have been used for other// cleanup in the meantime, for example by a Hibernate Session.if (this.holderActive) {// The thread-bound ConnectionHolder might not be available anymore,// since afterCompletion might get called from a different thread.TransactionSynchronizationManager.unbindResourceIfPossible(this.dataSource);this.holderActive = false;if (this.connectionHolder.hasConnection()) {releaseConnection(this.connectionHolder.getConnection(), this.dataSource);// Reset the ConnectionHolder: It might remain bound to the thread.this.connectionHolder.setConnection(null);}}this.connectionHolder.reset();}
Spring Boot Transaction 源码解析(二)相关推荐
- Spring Boot Transaction 源码解析(一)
目录 PlatformTransactionManager TransactionStatus DefaultTransactionStatus AbstractPlatformTransaction ...
- spring aop 注入源码解析
spring aop 注入源码解析 aop启动 AbstractApplicationContext.java @Overridepublic void refresh() throws BeansE ...
- spring aop 注入源码解析 1
spring aop 注入源码解析 aop启动 AbstractApplicationContext.java @Overridepublic void refresh() throws BeansE ...
- Spring 之 @Cacheable 源码解析(上)
一.@EnableCaching 源码解析 当要使用 @Cacheable 注解时需要引入 @EnableCaching 注解开启缓存功能.为什么呢?现在就来看看为什么要加入 @EnableCachi ...
- Spring 之 @Cacheable 源码解析(下)
CacheInterceptor 缓存切面处理逻辑 接着上篇 Spring 之 @Cacheable 源码解析(上) 说起,代理对象已经创建成功,接着分析调用流程.那么应该从哪里入手呢?当然是去看 A ...
- 【深度学习模型】智云视图中文车牌识别源码解析(二)
[深度学习模型]智云视图中文车牌识别源码解析(二) 感受 HyperLPR可以识别多种中文车牌包括白牌,新能源车牌,使馆车牌,教练车牌,武警车牌等. 代码不可谓不混乱(别忘了这是职业公司的准产品级代码 ...
- Spring Cloud Gateway 源码解析(3) —— Predicate
目录 RoutePredicateFactory GatewayPredicate AfterRoutePredicateFactory RoutePredicateHandlerMapping Fi ...
- spring 多线程 事务 源码解析(一)
大家好,我是烤鸭: 今天分享的是spring 多线程事务源码分析. 环境: spring-jdbc 5.0.4.REALEASE 今天分享一下spring事务的方法,这一篇还没涉及到多线程. 简单说一 ...
- erlang下lists模块sort(排序)方法源码解析(二)
上接erlang下lists模块sort(排序)方法源码解析(一),到目前为止,list列表已经被分割成N个列表,而且每个列表的元素是有序的(从大到小) 下面我们重点来看看mergel和rmergel ...
最新文章
- 独家 | TensorFlow 2.0将把Eager Execution变为默认执行模式,你该转向动态计算图了...
- Spring Workflow
- xhtml使用style属性
- zuulfilter添加例外_SpringCloud之Zuul 自定义filter
- zeppelin的安装与使用
- WIN 10 安装 Hadoop 2.7.7 + Spark 2.4.7 记录
- java concurrent int_java.util.concurrent.AtomicInteger
- 程序员等级测试,你不进来试试么?听说等级高的都进一线bat了!
- 微信小程序插件---表单验证篇
- 损失函数与代价函数区别
- MCU控制继电器的电路详解
- node的HTPP请求
- EPLAN2022——创建项目和图纸
- linux pwm控制蜂鸣器 滴滴_第七章----pwm蜂鸣器
- 高通|AR扫描图片播放视频
- 《数据库原理与应用》(第三版)习题参考答案
- 汉诺塔的递归逐步详解
- W3C标准包括什么?
- Java excel导入导出
- 【Axure教程】中继器版投票原型