Spring事务源码(二)
本文介绍Spring事务如果在当前存在事务是如何处理的
前言
在AbstractPlatformTransactionManager#getTransaction这个方法中取出事务对象transaction ,其内部封装了ConnectionHolder对象,这个对象是从线程变量中取出来的,如果取到了且判断是isTransactionActive的则说明当前线程已经开启过事务了,那么就会走handleExistingTransaction方法,按有事务的方式执行
@Override
public final TransactionStatus getTransaction(TransactionDefinition definition) throws TransactionException {
// 获取事务对象
Object transaction = doGetTransaction();
// Cache debug flag to avoid repeated checks.
boolean debugEnabled = logger.isDebugEnabled();
if (definition == null) {
// Use defaults if no transaction definition given.
definition = new DefaultTransactionDefinition();
}
// 判断当前线程是否有事务,如有则按执行handleExistingTransaction方法
if (isExistingTransaction(transaction)) {
// Existing transaction found -> check propagation behavior to find out how to behave.
return handleExistingTransaction(definition, transaction, debugEnabled);
}
// 以下省略
一、handleExistingTransaction
如果当前线程有事务存在,则调用此方法返回TransactionStatus 对象
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) {
Object suspendedResources = suspend(transaction);
boolean newSynchronization = (getTransactionSynchronization() == SYNCHRONIZATION_ALWAYS);
return prepareTransactionStatus(
definition, null, false, newSynchronization, debugEnabled, suspendedResources);
}
// 如果传播行为是PROPAGATION_NOT_SUPPORTED,则挂起当前线程,调用doBegin重新获取事务
if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRES_NEW) {
SuspendedResourcesHolder suspendedResources = suspend(transaction);
try {
boolean newSynchronization = (getTransactionSynchronization() != SYNCHRONIZATION_NEVER);
DefaultTransactionStatus status = newTransactionStatus(
definition, transaction, true, newSynchronization, debugEnabled, suspendedResources);
doBegin(transaction, definition);
prepareSynchronization(status, definition);
return status;
}
}
// 如果传播行为是PROPAGATION_NESTED,则对当前事务增加savePoint来实现内嵌事务
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'");
}
// 如果是通过给事务增加savePoint来实现内嵌事务
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这两种传播行为没有处理
// 是否需要校验事务的一些参数,通常是true的
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)"));
}
}
// 如果当前事务是readOnly的,但目标方法上的事务属性时非readOnly,那么抛出异常
if (!definition.isReadOnly()) {
if (TransactionSynchronizationManager.isCurrentTransactionReadOnly()) {
throw new IllegalTransactionStateException("Participating transaction with definition [" +
definition + "] is not marked as read-only but existing transaction is");
}
}
}
// 包装一下事务对象,事务属性,是否为新事务状态返回一个TransactionStatus对象
boolean newSynchronization = (getTransactionSynchronization() != SYNCHRONIZATION_NEVER);
return prepareTransactionStatus(definition, transaction, false, newSynchronization, debugEnabled, null);
}
二、suspendedResources
我们来看下Spring事务是如何通过此方法来实现挂起当前线程的
protected final SuspendedResourcesHolder suspend(Object transaction) throws TransactionException {
// 如果事务同步管理器属于激活状态,则需要多处理一下事务管理器的东西
if (TransactionSynchronizationManager.isSynchronizationActive()) {
// 取出事务同步器,清空事务同步管理器,并循环遍历调用下事务同步器的suspend方法
List<TransactionSynchronization> suspendedSynchronizations = doSuspendSynchronization();
try {
Object suspendedResources = null;
if (transaction != null) {
// 挂起事务,将当前事务即ConnectionHolder对象从事务变量中剔除并返回
suspendedResources = doSuspend(transaction);
}
// 取出当前事务的名称,readOnly,隔离级别,是否事务激活状态,并还原事务同步管理器的这些状态
String name = TransactionSynchronizationManager.getCurrentTransactionName();
TransactionSynchronizationManager.setCurrentTransactionName(null);
boolean readOnly = TransactionSynchronizationManager.isCurrentTransactionReadOnly();
TransactionSynchronizationManager.setCurrentTransactionReadOnly(false);
Integer isolationLevel = TransactionSynchronizationManager.getCurrentTransactionIsolationLevel();
TransactionSynchronizationManager.setCurrentTransactionIsolationLevel(null);
boolean wasActive = TransactionSynchronizationManager.isActualTransactionActive();
TransactionSynchronizationManager.setActualTransactionActive(false);
// 包装一个事务挂起资源对象的Holder
return new SuspendedResourcesHolder(
suspendedResources, suspendedSynchronizations, name, readOnly, isolationLevel, wasActive);
}
catch (RuntimeException ex) {
// doSuspend failed - original transaction is still active...
doResumeSynchronization(suspendedSynchronizations);
throw ex;
}
catch (Error err) {
// doSuspend failed - original transaction is still active...
doResumeSynchronization(suspendedSynchronizations);
throw err;
}
}
else if (transaction != null) {
// Transaction active but no synchronization active.
// 如果事务管理器属于不激活状态,仅仅挂机当前事务,将当前事务包装成suspendedResources
Object suspendedResources = doSuspend(transaction);
return new SuspendedResourcesHolder(suspendedResources);
}
else {
// Neither transaction nor synchronization active.
// 如果事务管理器属于不激活状态,且没有事务,那啥也做
return null;
}
}
三、doSuspend
具体挂机事务的方法:将事务对象中的ConnectionHolder设置为null,同时取出从线程变量中取出ConnectionHolder,并清除
@Override
protected Object doSuspend(Object transaction) {
DataSourceTransactionObject txObject = (DataSourceTransactionObject) transaction;
txObject.setConnectionHolder(null);
return TransactionSynchronizationManager.unbindResource(this.dataSource);
}
总结
提示:这里对文章进行总结:
例如:以上就是今天要讲的内容,本文仅仅简单介绍了pandas的使用,而pandas提供了大量能使我们快速便捷地处理数据的函数和方法。