spring---transaction(4)---源代码分析(事务的状态TransactionStatus)
写在前面
TransactionStatus表示一个具体的事务状态(这里应用到了Java的一个多继承,接口允许多继承)
TransactionStatus它继承了SavepointManager接口,SavepointManager是对事务中上述保存点功能的封装(Spring利用保存点功能实现了事务的嵌套功能。后面会详细说明)
public interface SavepointManager {
Object createSavepoint() throws TransactionException;
void rollbackToSavepoint(Object savepoint) throws TransactionException;
void releaseSavepoint(Object savepoint) throws TransactionException;
}
public interface TransactionStatus extends SavepointManager, Flushable {
//是否是一个新的事物
boolean isNewTransaction();
//是否有保存点
boolean hasSavepoint();
void setRollbackOnly();
//是否已被标记为回滚
boolean isRollbackOnly();
@Override
void flush();
boolean isCompleted();
}
DefaultTransactionStatus
常用的TransactionStatus接口实现为DefaultTransactionStatus:
public class DefaultTransactionStatus extends AbstractTransactionStatus {
private final Object transaction;
private final boolean newTransaction;
private final boolean newSynchronization;
private final boolean readOnly;
private final boolean debug;
private final Object suspendedResources;
}
目前jdbc事务是通过Connection来实现事务的,Hibernate是通过它自己定义的Transaction来实现的,所以各家的事务都不同,所以Spring只能以Object transaction的形式来表示各家的事务,事务的回滚和提交等操作都会最终委托给上述Object transaction来完成。
Object transaction的职责就是提交回滚事务,这个transaction的选择可能如下:
- DataSourceTransactionObject
- HibernateTransactionObject
- JpaTransactionObject
详细信息分别如下:
- DataSourceTransactionObject:
我们使用了dataSource来获取连接,要想实现事务功能,必然需要使用Connection,所以它中肯定有一个Connection来执行事务的操作。DataSourceTransactionObject中有一个ConnectionHolder,它封装了一个Connection。
- HibernateTransactionObject:
我们使用了hibenrate,此时要想实现事务功能,必然需要通过hibernate自己定义的Transaction来实现。
HibernateTransactionObject中含有一个SessionHolder,和上面的ConnectionHolder一样,它封装了一个Session,有了Session,我们就可以通过Session来产生一个Hibernate的Transaction,从而实现事务操作。
DefaultTransactionStatus的获取
DefaultTransactionStatus的获取是事务管理器的方法,这里的实现是AbstractPlatformTransactionManager提供的模板方法
在获取Object transaction之后,先进行判断,是否是已存在的事务。因为这个Object transaction的获取过程就是直接从线程绑定的获取的,可能当前线程已经存在事务
@Override
public final TransactionStatus getTransaction(TransactionDefinition definition) throws TransactionException {
//获取相应的Object transaction
Object transaction = doGetTransaction();
//就是依据和当前线程绑定的ConnectionHolder中是否已存在事务(也是依据和当前线程绑定的SessionHolder是否已存在事务)
if (isExistingTransaction(transaction)) {
//如果是已存在事务:则需要对事务的传播属性进行处理,如下即上述截图中的的handleExistingTransaction方法:
return handleExistingTransaction(definition, transaction, debugEnabled);
}
...
}
如果是已存在事务:则需要对事务的传播属性进行处理,如下即上述截图中的的handleExistingTransaction方法
private TransactionStatus handleExistingTransaction(
TransactionDefinition definition, Object transaction, boolean debugEnabled)
throws TransactionException {
// PROPAGATION_NEVER:不允许存在事务,如果存在抛出异常
if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NEVER) {
throw new IllegalTransactionStateException(
"Existing transaction found for transaction marked with propagation 'never'");
}
// PROPAGATION_NOT_SUPPORTED:不支持事务,如果存在事务,则需将事务挂起,保存起来,当执行完成之后,需要将挂起的事务继续恢复
if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NOT_SUPPORTED) {
if (debugEnabled) {
logger.debug("Suspending current transaction");
}
Object suspendedResources = suspend(transaction);
boolean newSynchronization = (getTransactionSynchronization() == SYNCHRONIZATION_ALWAYS);
return prepareTransactionStatus(
definition, null, false, newSynchronization, debugEnabled, suspendedResources);
}
//PROPAGATION_REQUIRES_NEW:开启一个新的事务,如果当前存在事务则把当前事务挂起来
if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRES_NEW) {
if (debugEnabled) {
logger.debug("Suspending current transaction, creating new transaction with name [" +
definition.getName() + "]");
}
SuspendedResourcesHolder suspendedResources = suspend(transaction);
try {
boolean newSynchronization = (getTransactionSynchronization() != SYNCHRONIZATION_NEVER);
DefaultTransactionStatus status = newTransactionStatus(
definition, transaction, true, newSynchronization, debugEnabled, suspendedResources);
//可以看到,创建新的事务,就会调用doBegin(transaction, definition);方法,将事务开启。
doBegin(transaction, definition);
prepareSynchronization(status, definition);
return status;
}
catch (RuntimeException beginEx) {
resumeAfterBeginException(transaction, suspendedResources, beginEx);
throw beginEx;
}
catch (Error beginErr) {
resumeAfterBeginException(transaction, suspendedResources, beginErr);
throw beginErr;
}
} if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NESTED) {
if (!isNestedTransactionAllowed()) {
throw new NestedTransactionNotSupportedException(
"Transaction manager does not allow nested transactions by default - " +
"specify 'nestedTransactionAllowed' property with value 'true'");
}
if (debugEnabled) {
logger.debug("Creating nested transaction with name [" + definition.getName() + "]");
}
if (useSavepointForNestedTransaction()) {
// Create savepoint within existing Spring-managed transaction,
// through the SavepointManager API implemented by TransactionStatus.
// Usually uses JDBC 3.0 savepoints. Never activates Spring synchronization.
DefaultTransactionStatus status =
prepareTransactionStatus(definition, transaction, false, false, debugEnabled, null);
status.createAndHoldSavepoint();
return status;
}
else {
// Nested transaction through nested begin and commit/rollback calls.
// Usually only for JTA: Spring synchronization might get activated here
// in case of a pre-existing JTA transaction.
boolean newSynchronization = (getTransactionSynchronization() != SYNCHRONIZATION_NEVER);
DefaultTransactionStatus status = newTransactionStatus(
definition, transaction, true, newSynchronization, debugEnabled, null);
doBegin(transaction, definition);
prepareSynchronization(status, definition);
return status;
}
} // Assumably PROPAGATION_SUPPORTS or PROPAGATION_REQUIRED.
//PROPAGATION_SUPPORTS 和 PROPAGATION_REQUIRED 如果当前存在事务,则仍旧使用该事物
if (debugEnabled) {
logger.debug("Participating in existing transaction");
}
if (isValidateExistingTransaction()) {
if (definition.getIsolationLevel() != TransactionDefinition.ISOLATION_DEFAULT) {
Integer currentIsolationLevel = TransactionSynchronizationManager.getCurrentTransactionIsolationLevel();
if (currentIsolationLevel == null || currentIsolationLevel != definition.getIsolationLevel()) {
Constants isoConstants = DefaultTransactionDefinition.constants;
throw new IllegalTransactionStateException("Participating transaction with definition [" +
definition + "] specifies isolation level which is incompatible with existing transaction: " +
(currentIsolationLevel != null ?
isoConstants.toCode(currentIsolationLevel, DefaultTransactionDefinition.PREFIX_ISOLATION) :
"(unknown)"));
}
}
if (!definition.isReadOnly()) {
if (TransactionSynchronizationManager.isCurrentTransactionReadOnly()) {
throw new IllegalTransactionStateException("Participating transaction with definition [" +
definition + "] is not marked as read-only but existing transaction is");
}
}
}
boolean newSynchronization = (getTransactionSynchronization() != SYNCHRONIZATION_NEVER);
return prepareTransactionStatus(definition, transaction, false, newSynchronization, debugEnabled, null);
}
事务的挂起
对于DataSourceTransactionManager来说,事务的挂起,就是把当前线程关联的ConnectionHolder解除绑定、同理事务的恢复就是把上述ConnectionHolder再重新绑定到当前线程,继续执行该事务
@Override
protected Object doSuspend(Object transaction) {
DataSourceTransactionObject txObject = (DataSourceTransactionObject) transaction;
txObject.setConnectionHolder(null);
//解除绑定dataSource, conHolder 至 TransactionSynchronizationManager
ConnectionHolder conHolder = (ConnectionHolder)
TransactionSynchronizationManager.unbindResource(this.dataSource);
return conHolder;
} @Override
protected void doResume(Object transaction, Object suspendedResources) {
ConnectionHolder conHolder = (ConnectionHolder) suspendedResources;
//重新绑定dataSource, conHolder 至 TransactionSynchronizationManager
TransactionSynchronizationManager.bindResource(this.dataSource, conHolder);
}
spring---transaction(4)---源代码分析(事务的状态TransactionStatus)的更多相关文章
- spring transaction源码分析--事务架构
1. 引言 事务特性 事务是并发控制的单元,是用户定义的一个操作序列.这些操作要么都做,要么都不做,是一个不可分割的工作单位.通过事务将逻辑相关的一组操作绑定在一起,以便服务器 保持数据的完整性.事 ...
- spring---transaction(1)---源代码分析(事务的拦截器TransactionInterceptor)
写在前面: 先了解一下spring的事务.分为分明式事务管理和注解式事务管理,对于前期的事务,spring会通过扫描拦截对于事务的方法进行增强(以后讲解). 若果目标方法存在事务,spring产出的b ...
- spring---transaction(3)---源代码分析(事务的管理器PlatformTransactionManager)
写在前面 由于实现事务功能的方式各不相同,Spring进行了统一的抽象,形成了PlatformTransactionManager事务管理器顶级接口(平台事务管理器),事务的提交.回滚等操作全部交给它 ...
- spring---transaction(2)---源代码分析(事务的定义TransactionDefinition)
写在前面 事务属性通过TransactionDefinition接口实现定义,主要有事务隔离级别.事务传播行为.事务超时时间.事务是否只读. public interface TransactionD ...
- 看透Spring MVC:源代码分析与实践 (Web开发技术丛书)
第一篇 网站基础知识 第1章 网站架构及其演变过程2 1.1 软件的三大类型2 1.2 基础的结构并不简单3 1.3 架构演变的起点5 1.4 海量数据的解决方案5 1.4.1 缓存和页面静态化5 1 ...
- spring(六):事务
事务特性ACID 原子性(Atomicity):即事务是不可分割的最小工作单元,事务内的操作要么全做,要么全不做: 一致性(Consistency):在事务执行前数据库的数据处于正确的状态,而事务执行 ...
- spring Transaction Propagation 事务传播
spring Transaction中有一个很重要的属性:Propagation.主要用来配置当前需要执行的方法,与当前是否有transaction之间的关系. 我晓得有点儿抽象,这也是为什么我想要写 ...
- 《深入实践Spring Boot》阅读笔记之三:核心技术源代码分析
刚关注的朋友,可以回顾前两篇文章: 基础应用开发 分布式应用开发 上篇文章总结了<深入实践Spring Boot>的第二部分,本篇文章总结第三部分,也是最后一部分.这部分主要讲解核心技术的 ...
- RocketMQ源码分析之RocketMQ事务消息实现原理中篇----事务消息状态回查
上节已经梳理了RocketMQ发送事务消息的流程(基于二阶段提交),本节将继续深入学习事务状态消息回查,我们知道,第一次提交到消息服务器时消息的主题被替换为RMQ_SYS_TRANS_HALF_TOP ...
随机推荐
- 深度解析:python之浅拷贝与深拷贝
深度解析python之浅拷贝与深拷贝 本文包括知识点: 1.copy与deepcopy 2.可变类型与不可变类型 1.copy与deepcopy 在日常python编码过程中,经常会遇见变量的赋值.这 ...
- 工作常用shell集合
<1>日志回滚案例======>[root@localhost test]# cat hbase.sh hbase_rotate_log () { log=$1; ...
- WebApi参数问题方案
原文:http://www.cnblogs.com/landeanfen/p/5337072.html
- 经典面试题:js继承方式下
上一篇讲解了构造函数的继承方式,今天来讲非构造函数的继承模式. 一.object()方法 json格式的发明人Douglas Crockford,提出了一个object()函数,可以做到这一点. fu ...
- Linux基础 - crontab
列出当前用户设置的定时任务 crontab -l 编辑定时任务 crontab -e 用法 m h dom mon dow * * * * * command 字段详解: *:any m: minut ...
- 2017-2018-2 20165301 实验四《Java面向对象程序设计》实验报告
2017-2018-2 20165301 实验四<Java面向对象程序设计>实验报告 一.Android Stuidio的安装测试 实验要求: 参考<Java和Android开发学习 ...
- cross apply 和 outer apply
使用APPLY运算符可以实现查询操作的外部表表达式返回的每个调用表值函数.表值函数作为右输入,外部表表达式作为左输入. 通过对右输入求值来获得左输入每一行的计算结果,生成的行被组合起来作为最终输出.A ...
- Writing a Kernel in C++
*:first-child { margin-top: 0 !important; } .markdown-body>*:last-child { margin-bottom: 0 !impor ...
- 一步一步学习IdentityServer3 (7)
在介绍自定义用户服务之前先对IdentityServerServiceFactory说明下 Idr3的服务工厂 下面有很多idr3提供的接口服务, 如:ViewService.UserService. ...
- 12 打印1到最大的n位数
输入数字 n,按顺序打印出从 1 最大的 n 位十进制数.比如输入 3,则打印出 1.2.3 一直到最大的 3 位数即 999.由于 n 可能会非常大,因此不能直接用 int 表示数字,而是用 cha ...