事务属性定义接口
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");