事务属性定义接口

TransactionDefinition是事务属性定义接口,保存事务定义的各种属性,如超时时间、隔离级别、传播属性等。

public interface TransactionDefinition {
//获取事务传播类型
int getPropagationBehavior();

//获取事务隔离级别
int getIsolationLevel();

//获取事务超时时间
int getTimeout();

//事务的只读性
boolean isReadOnly();

//获取事务名称
String getName();

}

事务实例接口

TransactionStatus是事务实例接口,表示了当前事务在内存中的一个实例,从名字来看保存了事务的运行状态信息。
AbstractTransactionStatus是抽象实现,DefaultTransactionStatus是事务实例的默认实现。

事务管理器

PlatformTransactionManager是Spring事务的核心接口,一般不会直接使用该接口,应用程序可以直接用TransactionTemplate或者AOP进行事务操作。AbstractPlatformTransactionManager是PlatformTransactionManager的抽象类实现。

public interface PlatformTransactionManager {

//根据事务指定的策略获取激活的事务或者重新创建一个事务。
TransactionStatus getTransaction(TransactionDefinition definition) throws TransactionException;

//提交事务
void commit(TransactionStatus status) throws TransactionException;

//回滚事务
void rollback(TransactionStatus status) throws TransactionException;

}

AbstractPlatformTransactionManager定义事务实现的骨架。

获取事务

getTransaction(TransactionDefinition definition)主要逻辑是首先获取当前线程的事务:

Object transaction = doGetTransaction();

注意doGetTransaction是个钩子方法,负责子类方法的回调,凡是以do开头的方法都类似,后续不在赘述。

如果当前线程已经存在事务,则handleExistingTransaction(definition, transaction, debugEnabled),这个方法根据配置的事务策略处理存在的事务:

if (isExistingTransaction(transaction)) {
// Existing transaction found -> check propagation behavior to find out how to behave.
return handleExistingTransaction(definition, transaction, debugEnabled);
}

如果当前线程不存在事务,则开启新事务:

else if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRED ||
definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRES_NEW ||
definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NESTED) {
SuspendedResourcesHolder suspendedResources = suspend(null);
if (debugEnabled) {
logger.debug("Creating new transaction with name [" + definition.getName() + "]: " + definition);
}
try {
boolean newSynchronization = (getTransactionSynchronization() != SYNCHRONIZATION_NEVER);
DefaultTransactionStatus status = newTransactionStatus(
definition, transaction, true, newSynchronization, debugEnabled, suspendedResources);
doBegin(transaction, definition);
prepareSynchronization(status, definition);
return status;
}
catch (RuntimeException ex) {
resume(null, suspendedResources);
throw ex;
}
catch (Error err) {
resume(null, suspendedResources);
throw err;
}

我们选择DataSourceTransactionManager的doBegin看看,里面设置事务为手动提交模式,然后激活当前事务:

// 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); //设置为手动提交
}
txObject.getConnectionHolder().setTransactionActive(true);

事务提交

主要实现方法是processCommit,在事务提交之前还做了其他额外准备操作,然后执行doCommit方法,出错时不会进行资源清理操作,不做回滚操作,回滚操作由调用者发起。

private void processCommit(DefaultTransactionStatus status) throws TransactionException {
try {
boolean beforeCompletionInvoked = false;
try {
prepareForCommit(status);
triggerBeforeCommit(status);
triggerBeforeCompletion(status);
beforeCompletionInvoked = true;
boolean globalRollbackOnly = false;
if (status.isNewTransaction() || isFailEarlyOnGlobalRollbackOnly()) {
globalRollbackOnly = status.isGlobalRollbackOnly();
}
if (status.hasSavepoint()) {
if (status.isDebug()) {
logger.debug("Releasing transaction savepoint");
}
status.releaseHeldSavepoint();
}
else if (status.isNewTransaction()) {
if (status.isDebug()) {
logger.debug("Initiating transaction commit");
}
doCommit(status);
}
// Throw UnexpectedRollbackException if we have a global rollback-only
// marker but still didn't get a corresponding exception from commit.
if (globalRollbackOnly) {
throw new UnexpectedRollbackException(
"Transaction silently rolled back because it has been marked as rollback-only");
}
}
catch (UnexpectedRollbackException ex) {
// can only be caused by doCommit
triggerAfterCompletion(status, TransactionSynchronization.STATUS_ROLLED_BACK);
throw ex;
}

...

事务回滚

public final void rollback(TransactionStatus status) throws TransactionException {
if (status.isCompleted()) {
throw new IllegalTransactionStateException(
"Transaction is already completed - do not call commit or rollback more than once per transaction");
}

DefaultTransactionStatus defStatus = (DefaultTransactionStatus) status;
processRollback(defStatus);
}

事务同步管理器

TransactionSynchronizationManager关键实现是依赖ThreadLocal。各种数据库资源保存在各自线程的副本中,保证线程安全,典型的用空间换时间的做法。

private static final ThreadLocal<Map<Object, Object>> resources =
new NamedThreadLocal<Map<Object, Object>>("Transactional resources");

private static final ThreadLocal<Set<TransactionSynchronization>> synchronizations =
new NamedThreadLocal<Set<TransactionSynchronization>>("Transaction synchronizations");

private static final ThreadLocal<String> currentTransactionName =
new NamedThreadLocal<String>("Current transaction name");

private static final ThreadLocal<Boolean> currentTransactionReadOnly =
new NamedThreadLocal<Boolean>("Current transaction read-only status");

private static final ThreadLocal<Integer> currentTransactionIsolationLevel =
new NamedThreadLocal<Integer>("Current transaction isolation level");

private static final ThreadLocal<Boolean> actualTransactionActive =
new NamedThreadLocal<Boolean>("Actual transaction active");