spring的事务管理主体上分为两部分,一部分是通知代理的创建,另一部分Interceptor的环绕通知。
本文先分析Interceptor的环绕通知,通知代理的创建我们暂时不做分析。
Interceptor的环绕通知
@EnableTransactionManagement注解
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(TransactionManagementConfigurationSelector.class)
public @interface EnableTransactionManagement {
}
看到EnableTransactionManagement导入了TransactionManagementConfigurationSelector,就是说会将selectImports方法返回的组件导入到spring容器。
TransactionManagementConfigurationSelector类
这个类实现了ImportSelector接口,这个接口的作用之前说明过:
public class TransactionManagementConfigurationSelector
extends AdviceModeImportSelector<EnableTransactionManagement> {
@Override
protected String[] selectImports(AdviceMode adviceMode) {
switch (adviceMode) {
// 默认走这个分支
// 可以看到导入了AutoProxyRegistrar和ProxyTransactionManagementConfiguration
// AutoProxyRegistrar是创建代理使用的,暂时不展开分析
// ProxyTransactionManagementConfiguration是spring事务的核心配置类
case PROXY:
return new String[] {AutoProxyRegistrar.class.getName(),
ProxyTransactionManagementConfiguration.class.getName()};
case ASPECTJ:
return new String[] {determineTransactionAspectClass()};
default:
return null;
}
}
private String determineTransactionAspectClass() {
return (ClassUtils.isPresent("javax.transaction.Transactional", getClass().getClassLoader()) ?
TransactionManagementConfigUtils.JTA_TRANSACTION_ASPECT_CONFIGURATION_CLASS_NAME :
TransactionManagementConfigUtils.TRANSACTION_ASPECT_CONFIGURATION_CLASS_NAME);
}
}
ProxyTransactionManagementConfiguration类
@Configuration(proxyBeanMethods = false)
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
public class ProxyTransactionManagementConfiguration extends AbstractTransactionManagementConfiguration {
@Bean(name = TransactionManagementConfigUtils.TRANSACTION_ADVISOR_BEAN_NAME)
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
public BeanFactoryTransactionAttributeSourceAdvisor transactionAdvisor(
TransactionAttributeSource transactionAttributeSource,
TransactionInterceptor transactionInterceptor) {
BeanFactoryTransactionAttributeSourceAdvisor advisor =
new BeanFactoryTransactionAttributeSourceAdvisor();
advisor.setTransactionAttributeSource(transactionAttributeSource);
advisor.setAdvice(transactionInterceptor);
if (this.enableTx != null) {
advisor.setOrder(this.enableTx.<Integer>getNumber("order"));
}
return advisor;
}
@Bean
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
public TransactionAttributeSource transactionAttributeSource() {
return new AnnotationTransactionAttributeSource();
}
@Bean
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
public TransactionInterceptor transactionInterceptor(
TransactionAttributeSource transactionAttributeSource) {
TransactionInterceptor interceptor = new TransactionInterceptor();
interceptor.setTransactionAttributeSource(transactionAttributeSource);
if (this.txManager != null) {
interceptor.setTransactionManager(this.txManager);
}
return interceptor;
}
}
就是一个普通的配置类,和我们写的ServiceLogConfiguration类似,最核心的就是创建了一个Advisor对象,这个对象中保存的PointCut和Interceptor实现了环绕通知的功能。
而在这里,使用TransactionAttributeSourcePointcut实现了切入点的判断,这个是通知代理创建时使用的,我们暂时不做分析。我们下面看一下如何使用TransactionInterceptor来实现事务的环绕通知。
TransactionInterceptor类
invoke方法实现环绕通知
public Object invoke(MethodInvocation invocation) throws Throwable {
// Work out the target class: may be {@code null}.
// The TransactionAttributeSource should be passed the target class
// as well as the method, which may be from an interface.
Class<?> targetClass =
(invocation.getThis() != null ? AopUtils.getTargetClass(invocation.getThis()) : null);
// Adapt to TransactionAspectSupport's invokeWithinTransaction...
return invokeWithinTransaction(invocation.getMethod(), targetClass, invocation::proceed);
}
// 核心的环绕通知实现方法
protected Object invokeWithinTransaction(Method method, @Nullable Class<?> targetClass,
final InvocationCallback invocation) throws Throwable {
// If the transaction attribute is null, the method is non-transactional.
// 这里获取到的是一个AnnotationTransactionAttributeSource实现,
// 封装了SpringTransactionAnnotationParser用于解析Transactional注解
TransactionAttributeSource tas = getTransactionAttributeSource();
// 这里获取到的是一个RuleBasedTransactionAttribute对象,
// 封装目标方法事务相关的属性,主要包括:rollbackFor、propagationBehavior、isolationLevel等
// 后续开启事务时还会使用到这个对象
final TransactionAttribute txAttr = (tas != null ? tas.getTransactionAttribute(method, targetClass) : null);
// 获取事务管理器,方法中有几种检索机制,不做展开分析,如果不做特殊配置就是从spring容器中获取事务管理器
final TransactionManager tm = determineTransactionManager(txAttr);
// 这个分支判断响应式事务,暂时不做分析
if (this.reactiveAdapterRegistry != null && tm instanceof ReactiveTransactionManager) {
// ...
return txSupport.invokeWithinTransaction(
method, targetClass, invocation, txAttr, (ReactiveTransactionManager) tm);
}
// 转一下类型
PlatformTransactionManager ptm = asPlatformTransactionManager(tm);
final String joinpointIdentification = methodIdentification(method, targetClass, txAttr);
// 由于我们使用的是DataSourceTransactionManager实现,所以总是走这个分支
if (txAttr == null || !(ptm instanceof CallbackPreferringPlatformTransactionManager)) {
// Standard transaction demarcation with getTransaction and commit/rollback calls.
// 在这里开启事务,这样说不是很准确,因为propagation不同,内部的逻辑也会不同
TransactionInfo txInfo = createTransactionIfNecessary(ptm, txAttr, joinpointIdentification);
Object retVal;
try {
// This is an around advice: Invoke the next interceptor in the chain.
// This will normally result in a target object being invoked.
retVal = invocation.proceedWithInvocation();
} catch (Throwable ex) {
// target invocation exception
// 回滚事务,暂时使用这种不准确的说法
completeTransactionAfterThrowing(txInfo, ex);
throw ex;
} finally {
// 做一些清理工作
cleanupTransactionInfo(txInfo);
}
if (retVal != null && vavrPresent && VavrDelegate.isVavrTry(retVal)) {
// Set rollback-only in case of Vavr failure matching our rollback rules...
TransactionStatus status = txInfo.getTransactionStatus();
if (status != null && txAttr != null) {
retVal = VavrDelegate.evaluateTryFailure(retVal, txAttr, status);
}
}
// 提交事务,暂时使用这种不准确的说法
commitTransactionAfterReturning(txInfo);
return retVal;
} else {
// 这个分支暂时不做分析
Object result;
final ThrowableHolder throwableHolder = new ThrowableHolder();
// ...
return result;
}
}
createTransactionIfNecessary方法
protected TransactionInfo createTransactionIfNecessary(@Nullable PlatformTransactionManager tm,
@Nullable TransactionAttribute txAttr, final String joinpointIdentification) {
// If no name specified, apply method identification as transaction name.
if (txAttr != null && txAttr.getName() == null) {
txAttr = new DelegatingTransactionAttribute(txAttr) {
@Override
public String getName() {
return joinpointIdentification;
}
};
}
TransactionStatus status = null;
if (txAttr != null) {
if (tm != null) {
// 这里创建事务或返回当前事务
// Return a currently active transaction or create a new one,
// according to the specified propagation behavior.
// Note that parameters like isolation level or timeout will
// only be applied to new transactions, and thus be ignored when participating in active ones.
// Furthermore, not all transaction definition settings will be
// supported by every transaction manager: A proper transaction manager
// implementation should throw an exception when unsupported settings are encountered.
// An exception to the above rule is the read-only flag, which should be ignored
// if no explicit read-only mode is supported. Essentially,
// the read-only flag is just a hint for potential optimization.
status = tm.getTransaction(txAttr);
} else {
if (logger.isDebugEnabled()) {
logger.debug("");
}
}
}
// Prepare a TransactionInfo for the given attribute and status object.
// 最重要的是把事务绑定到当前线程上
return prepareTransactionInfo(tm, txAttr, joinpointIdentification, status);
}
prepareTransactionInfo方法
protected TransactionInfo prepareTransactionInfo(PlatformTransactionManager tm,
TransactionAttribute txAttr, String joinpointIdentification,
TransactionStatus status) {
TransactionInfo txInfo = new TransactionInfo(tm, txAttr, joinpointIdentification);
if (txAttr != null) {
// We need a transaction for this method...
if (logger.isTraceEnabled()) {
logger.trace("Getting transaction for [" + txInfo.getJoinpointIdentification() + "]");
}
// The transaction manager will flag an error if an incompatible tx already exists.
txInfo.newTransactionStatus(status);
} else {
// The TransactionInfo.hasTransaction() method will return false. We created it only
// to preserve the integrity of the ThreadLocal stack maintained in this class.
if (logger.isTraceEnabled()) {
logger.trace("No need to create transaction for [" + joinpointIdentification +
"]: This method is not transactional.");
}
}
// 把事务绑定到线程上
// We always bind the TransactionInfo to the thread, even if we didn't create
// a new transaction here. This guarantees that the TransactionInfo stack
// will be managed correctly even if no transaction was created by this aspect.
txInfo.bindToThread();
return txInfo;
}
// txInfo.bindToThread()
private void bindToThread() {
// Expose current TransactionStatus, preserving any existing TransactionStatus
// for restoration after this transaction is complete.
// transactionInfoHolder是一个ThreadLocal<TransactionInfo>对象
this.oldTransactionInfo = transactionInfoHolder.get();
transactionInfoHolder.set(this);
}
PlatformTransactionManager.getTransaction方法(重点)
这个方法很重要。
TransactionStatus getTransaction(@Nullable TransactionDefinition definition)
throws TransactionException;
API文档是这样写的:
Return a currently active transaction or create a new one, according to the specified propagation behavior.
Note that parameters like isolation level or timeout will only be applied to new transactions, and thus be ignored when participating in active ones.
Furthermore, not all transaction definition settings will be supported by every transaction manager: A proper transaction manager implementation should throw an exception when unsupported settings are encountered.
An exception to the above rule is the read-only flag, which should be ignored if no explicit read-only mode is supported. Essentially, the read-only flag is just a hint for potential optimization.
--
根据指定的传播行为,返回当前活动的事务或创建一个新事务。隔离级别、超时等参数仅适用于新事务,因此在参与活动事务时会被忽略。
此外,并非每个事务管理器都支持所有事务定义设置:当遇到不支持的设置时,正确的事务管理器实现应该抛出异常。
上述规则的一个例外是只读标志,如果不支持显式只读模式,则应忽略该标志。本质上,只读标志只是潜在优化的提示。
AbstractPlatformTransactionManager.getTransaction方法实现(重点)
AbstractPlatformTransactionManager类实现了getTransaction方法,内部代码很重要,所以全部记录下来了:
public final TransactionStatus getTransaction(@Nullable TransactionDefinition definition)
throws TransactionException {
// Use defaults if no transaction definition given.
TransactionDefinition def = (definition != null ? definition : TransactionDefinition.withDefaults());
// 这是一个抽象方法,在DataSourceTransactionManager返回的是DataSourceTransactionObject对象
// 内部会持有一个ConnectionHolder的引用,用于获取当前线程上的Connection
// 另外还有transactionActive、savepointsSupported等
Object transaction = doGetTransaction();
boolean debugEnabled = logger.isDebugEnabled();
// 当前已经存在事务
if (isExistingTransaction(transaction)) {
// Existing transaction found -> check propagation behavior to find out how to behave.
return handleExistingTransaction(def, transaction, debugEnabled);
}
// Check definition settings for new transaction.
if (def.getTimeout() < TransactionDefinition.TIMEOUT_DEFAULT) {
throw new InvalidTimeoutException("Invalid transaction timeout", def.getTimeout());
}
// No existing transaction found -> check propagation behavior to find out how to proceed.
if (def.getPropagationBehavior() == TransactionDefinition.PROPAGATION_MANDATORY) {
// MANDATORY - Support a current transaction, throw an exception if none exists.
throw new IllegalTransactionStateException(
"No existing transaction found for transaction marked with propagation 'mandatory'");
} else if (def.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRED ||
def.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRES_NEW ||
def.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NESTED) {
// REQUIRED, REQUIRES_NEW, NESTED
SuspendedResourcesHolder suspendedResources = suspend(null);
if (debugEnabled) {
logger.debug("Creating new transaction with name [" + def.getName() + "]: " + def);
}
try {
return startTransaction(def, transaction, debugEnabled, suspendedResources);
} catch (RuntimeException | Error ex) {
resume(null, suspendedResources);
throw ex;
}
} else {
// Create "empty" transaction: no actual transaction, but potentially synchronization.
// 创建空事务:没有实际事务,但可能是同步的
if (def.getIsolationLevel() != TransactionDefinition.ISOLATION_DEFAULT && logger.isWarnEnabled()) {
logger.warn("Custom isolation level specified but no actual transaction initiated; " +
"isolation level will effectively be ignored: " + def);
}
boolean newSynchronization = (getTransactionSynchronization() == SYNCHRONIZATION_ALWAYS);
return prepareTransactionStatus(def, null, true, newSynchronization, debugEnabled, null);
}
}
DataSourceTransactionManager.doGetTransaction方法
protected Object doGetTransaction() {
DataSourceTransactionObject txObject = new DataSourceTransactionObject();
txObject.setSavepointAllowed(isNestedTransactionAllowed());
// 使用dataSource获取当前线程上的ConnectionHolder
// TransactionSynchronizationManager类管理着需要在线程本地保存的资源,后续会详细分析这个类
ConnectionHolder conHolder =
(ConnectionHolder) TransactionSynchronizationManager.getResource(obtainDataSource());
txObject.setConnectionHolder(conHolder, false);
return txObject;
}
DataSourceTransactionManager.isExistingTransaction方法
protected boolean isExistingTransaction(Object transaction) {
DataSourceTransactionObject txObject = (DataSourceTransactionObject) transaction;
return (txObject.hasConnectionHolder() && txObject.getConnectionHolder().isTransactionActive());
}
当前存在事务的处理逻辑
handleExistingTransaction方法
如果当前已经存在了事务,那么会使用这个方法处理:
private TransactionStatus handleExistingTransaction(
TransactionDefinition definition, Object transaction, boolean debugEnabled)
throws TransactionException {
// NEVER - Execute non-transactionally, throw an exception if a transaction exists.
if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NEVER) {
throw new IllegalTransactionStateException(
"Existing transaction found for transaction marked with propagation 'never'");
}
// NOT_SUPPORTED - Execute non-transactionally, suspend the current transaction if one exists.
if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NOT_SUPPORTED) {
// 挂起当前事务
Object suspendedResources = suspend(transaction);
boolean newSynchronization = (getTransactionSynchronization() == SYNCHRONIZATION_ALWAYS);
return prepareTransactionStatus(
definition, null, false, newSynchronization, debugEnabled, suspendedResources);
}
// REQUIRES_NEW - Create a new transaction, and suspend the current transaction if one exists.
if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRES_NEW) {
SuspendedResourcesHolder suspendedResources = suspend(transaction);
try {
return startTransaction(definition, transaction, debugEnabled, suspendedResources);
} catch (RuntimeException | Error beginEx) {
resumeAfterBeginException(transaction, suspendedResources, beginEx);
throw beginEx;
}
}
// NESTED - Execute within a nested transaction if a current transaction exists,
// behave like REQUIRED otherwise.
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 (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.
return startTransaction(definition, transaction, debugEnabled, null);
}
}
// Assumably PROPAGATION_SUPPORTS or PROPAGATION_REQUIRED.
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);
}
NOT_SUPPORTED的处理
// NOT_SUPPORTED - Execute non-transactionally, suspend the current transaction if one exists.
if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NOT_SUPPORTED) {
// 挂起当前事务
Object suspendedResources = suspend(transaction);
// 这里是true
boolean newSynchronization = (getTransactionSynchronization() == SYNCHRONIZATION_ALWAYS);
// TransactionStatus返回
return prepareTransactionStatus(
definition, null, false, newSynchronization, debugEnabled, suspendedResources);
}
挂起当前事务:
// 实际上就是把当前事务的相关状态通过SuspendedResourcesHolder保存到TransactionStatus中
// 等待后续恢复该事务
protected final SuspendedResourcesHolder suspend(@Nullable Object transaction) throws TransactionException {
if (TransactionSynchronizationManager.isSynchronizationActive()) {
List<TransactionSynchronization> suspendedSynchronizations = doSuspendSynchronization();
try {
Object suspendedResources = null;
if (transaction != null) {
suspendedResources = doSuspend(transaction);
}
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 for suspended resources.
return new SuspendedResourcesHolder(
suspendedResources, suspendedSynchronizations, name, readOnly, isolationLevel, wasActive);
} catch (RuntimeException | Error ex) {
// doSuspend failed - original transaction is still active...
doResumeSynchronization(suspendedSynchronizations);
throw ex;
}
} else if (transaction != null) {
// Transaction active but no synchronization active.
Object suspendedResources = doSuspend(transaction);
return new SuspendedResourcesHolder(suspendedResources);
} else {
// Neither transaction nor synchronization active.
return null;
}
}
// DataSourceTransactionManager类的实现返回的是一个ConnectionHolder对象
// 就是把待挂起的事务的连接保存起来,后续恢复事务时使用
protected Object doSuspend(Object transaction) {
DataSourceTransactionObject txObject = (DataSourceTransactionObject) transaction;
txObject.setConnectionHolder(null);
return TransactionSynchronizationManager.unbindResource(obtainDataSource());
}
Create a new TransactionStatus for the given arguments, also initializing transaction synchronization as appropriate.
protected final DefaultTransactionStatus prepareTransactionStatus(
TransactionDefinition definition, @Nullable Object transaction, boolean newTransaction,
boolean newSynchronization, boolean debug, @Nullable Object suspendedResources) {
DefaultTransactionStatus status = newTransactionStatus(
definition, transaction, newTransaction, newSynchronization, debug, suspendedResources);
prepareSynchronization(status, definition);
return status;
}
protected DefaultTransactionStatus newTransactionStatus(
TransactionDefinition definition, @Nullable Object transaction, boolean newTransaction,
boolean newSynchronization, boolean debug, @Nullable Object suspendedResources) {
boolean actualNewSynchronization = newSynchronization &&
!TransactionSynchronizationManager.isSynchronizationActive();
return new DefaultTransactionStatus(
transaction, newTransaction, actualNewSynchronization,
definition.isReadOnly(), debug, suspendedResources);
}
// 根据需要初始化事务同步
protected void prepareSynchronization(DefaultTransactionStatus status, TransactionDefinition definition) {
if (status.isNewSynchronization()) {
TransactionSynchronizationManager.setActualTransactionActive(status.hasTransaction());
TransactionSynchronizationManager.setCurrentTransactionIsolationLevel(
definition.getIsolationLevel() != TransactionDefinition.ISOLATION_DEFAULT ?
definition.getIsolationLevel() : null);
TransactionSynchronizationManager.setCurrentTransactionReadOnly(definition.isReadOnly());
TransactionSynchronizationManager.setCurrentTransactionName(definition.getName());
TransactionSynchronizationManager.initSynchronization();
}
}
REQUIRES_NEW的处理
// REQUIRES_NEW - Create a new transaction, and suspend the current transaction if one exists.
if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRES_NEW) {
// 挂起当前事务
SuspendedResourcesHolder suspendedResources = suspend(transaction);
try {
// 开启新事务
return startTransaction(definition, transaction, debugEnabled, suspendedResources);
} catch (RuntimeException | Error beginEx) {
resumeAfterBeginException(transaction, suspendedResources, beginEx);
throw beginEx;
}
}
开启新事务:
private TransactionStatus startTransaction(TransactionDefinition definition, Object transaction,
boolean debugEnabled, @Nullable SuspendedResourcesHolder suspendedResources) {
// 这里是true
boolean newSynchronization = (getTransactionSynchronization() != SYNCHRONIZATION_NEVER);
DefaultTransactionStatus status = newTransactionStatus(
definition, transaction, true, newSynchronization, debugEnabled, suspendedResources);
// 开启新事务
doBegin(transaction, definition);
// 根据需要初始化事务同步
prepareSynchronization(status, definition);
return status;
}
// DataSourceTransactionManager.doBegin
protected void doBegin(Object transaction, TransactionDefinition definition) {
DataSourceTransactionObject txObject = (DataSourceTransactionObject) transaction;
Connection con = null;
try {
// 由于之前挂起事务时已经txObject.setConnectionHolder(null)了
// 所以!txObject.hasConnectionHolder()=true
if (!txObject.hasConnectionHolder() ||
txObject.getConnectionHolder().isSynchronizedWithTransaction()) {
// 获取一个新连接,并创建ConnectionHolder
Connection newCon = obtainDataSource().getConnection();
txObject.setConnectionHolder(new ConnectionHolder(newCon), true);
}
txObject.getConnectionHolder().setSynchronizedWithTransaction(true);
con = 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);
con.setAutoCommit(false);
}
prepareTransactionalConnection(con, definition);
txObject.getConnectionHolder().setTransactionActive(true);
int timeout = determineTimeout(definition);
if (timeout != TransactionDefinition.TIMEOUT_DEFAULT) {
txObject.getConnectionHolder().setTimeoutInSeconds(timeout);
}
// Bind the connection holder to the thread.
// 把连接绑定到线程上
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);
}
}
NESTED的处理
// NESTED - Execute within a nested transaction if a current transaction exists,
// behave like REQUIRED otherwise.
if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NESTED) {
// 这里是false
// 因为在创建DataSourceTransactionManager的时候为nestedTransactionAllowed设置了true
if (!isNestedTransactionAllowed()) {
throw new NestedTransactionNotSupportedException(
"Transaction manager does not allow nested transactions by default - " +
"specify 'nestedTransactionAllowed' property with value 'true'");
}
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.
// 这个是创建一个新的TransactionStatus对象,之前看过里面的代码,此处略
DefaultTransactionStatus status =
prepareTransactionStatus(definition, transaction, false, false, debugEnabled, null);
// 这里是设置保存点,之后如果子事务出错,就回滚到此保存点
// 内部实际上就是找到当前事务的数据库连接,调用数据库连接的设置保存点方法
status.createAndHoldSavepoint();
return status;
} else {
// JtaTransactionManager实现会进入这个分支
// 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.
return startTransaction(definition, transaction, debugEnabled, null);
}
}
status.createAndHoldSavepoint()方法:
public void createAndHoldSavepoint() throws TransactionException {
setSavepoint(getSavepointManager().createSavepoint());
}
// getSavepointManager()方法获取到的是一个DataSourceTransactionObject对象
protected SavepointManager getSavepointManager() {
Object transaction = this.transaction;
if (!(transaction instanceof SavepointManager)) {
throw new NestedTransactionNotSupportedException(
"Transaction object [" + this.transaction + "] does not support savepoints");
}
return (SavepointManager) transaction;
}
// JdbcTransactionObjectSupport.createSavepoint()
public Object createSavepoint() throws TransactionException {
ConnectionHolder conHolder = getConnectionHolderForSavepoint();
try {
if (!conHolder.supportsSavepoints()) {
throw new NestedTransactionNotSupportedException("");
}
if (conHolder.isRollbackOnly()) {
throw new CannotCreateTransactionException("");
}
return conHolder.createSavepoint();
} catch (SQLException ex) {
throw new CannotCreateTransactionException("Could not create JDBC savepoint", ex);
}
}
// conHolder.createSavepoint()
public Savepoint createSavepoint() throws SQLException {
this.savepointCounter++;
// 调用数据库连接的设置保存点方法
return getConnection().setSavepoint(SAVEPOINT_NAME_PREFIX + this.savepointCounter);
}
SUPPORTS、REQUIRED和MANDATORY的处理
// Assumably PROPAGATION_SUPPORTS or PROPAGATION_REQUIRED.
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);
当前无事务的处理逻辑
// No existing transaction found -> check propagation behavior to find out how to proceed.
if (def.getPropagationBehavior() == TransactionDefinition.PROPAGATION_MANDATORY) {
// MANDATORY - Support a current transaction, throw an exception if none exists.
throw new IllegalTransactionStateException(
"No existing transaction found for transaction marked with propagation 'mandatory'");
} else if (def.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRED ||
def.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRES_NEW ||
def.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NESTED) {
// REQUIRED, REQUIRES_NEW, NESTED
SuspendedResourcesHolder suspendedResources = suspend(null);
if (debugEnabled) {
logger.debug("Creating new transaction with name [" + def.getName() + "]: " + def);
}
try {
return startTransaction(def, transaction, debugEnabled, suspendedResources);
} catch (RuntimeException | Error ex) {
resume(null, suspendedResources);
throw ex;
}
} else {
// Create "empty" transaction: no actual transaction, but potentially synchronization.
// 创建空事务:没有实际事务,但可能是同步的
if (def.getIsolationLevel() != TransactionDefinition.ISOLATION_DEFAULT && logger.isWarnEnabled()) {
logger.warn("Custom isolation level specified but no actual transaction initiated; " +
"isolation level will effectively be ignored: " + def);
}
boolean newSynchronization = (getTransactionSynchronization() == SYNCHRONIZATION_ALWAYS);
return prepareTransactionStatus(def, null, true, newSynchronization, debugEnabled, null);
}
执行目标方法
在createTransactionIfNecessary之后会使用TransactionInfo封装事务信息:
protected static final class TransactionInfo {
private final PlatformTransactionManager transactionManager;
private final TransactionAttribute transactionAttribute;
private final String joinpointIdentification;
private TransactionStatus transactionStatus;
private TransactionInfo oldTransactionInfo;
}
主要就是TransactionManager和TransactionStatus等信息。
之后就要执行目标方法了,这部分没有值得多写的,就略过了。
提交事务
入口
commitTransactionAfterReturning(txInfo);
protected void commitTransactionAfterReturning(@Nullable TransactionInfo txInfo) {
if (txInfo != null && txInfo.getTransactionStatus() != null) {
txInfo.getTransactionManager().commit(txInfo.getTransactionStatus());
}
}
提交事务
public final void commit(TransactionStatus status) throws TransactionException {
if (status.isCompleted()) {
throw new IllegalTransactionStateException("");
}
DefaultTransactionStatus defStatus = (DefaultTransactionStatus) status;
if (defStatus.isLocalRollbackOnly()) {
processRollback(defStatus, false);
return;
}
if (!shouldCommitOnGlobalRollbackOnly() && defStatus.isGlobalRollbackOnly()) {
processRollback(defStatus, true);
return;
}
// 提交事务
processCommit(defStatus);
}
private void processCommit(DefaultTransactionStatus status) throws TransactionException {
try {
boolean beforeCompletionInvoked = false;
try {
boolean unexpectedRollback = false;
prepareForCommit(status);
triggerBeforeCommit(status);
triggerBeforeCompletion(status);
beforeCompletionInvoked = true;
// 处理NESTED
if (status.hasSavepoint()) {
unexpectedRollback = status.isGlobalRollbackOnly();
status.releaseHeldSavepoint();
} else if (status.isNewTransaction()) {
// 使用doCommit处理新事务
unexpectedRollback = status.isGlobalRollbackOnly();
doCommit(status);
} else if (isFailEarlyOnGlobalRollbackOnly()) {
unexpectedRollback = status.isGlobalRollbackOnly();
}
// Throw UnexpectedRollbackException if we have a global rollback-only
// marker but still didn't get a corresponding exception from commit.
if (unexpectedRollback) {
throw new UnexpectedRollbackException("");
}
} catch (UnexpectedRollbackException ex) {
// can only be caused by doCommit
triggerAfterCompletion(status, TransactionSynchronization.STATUS_ROLLED_BACK);
throw ex;
} catch (TransactionException ex) {
// can only be caused by doCommit
if (isRollbackOnCommitFailure()) {
doRollbackOnCommitException(status, ex);
} else {
triggerAfterCompletion(status, TransactionSynchronization.STATUS_UNKNOWN);
}
throw ex;
} catch (RuntimeException | Error ex) {
if (!beforeCompletionInvoked) {
triggerBeforeCompletion(status);
}
doRollbackOnCommitException(status, ex);
throw ex;
}
// Trigger afterCommit callbacks, with an exception thrown there
// propagated to callers but the transaction still considered as committed.
try {
triggerAfterCommit(status);
} finally {
triggerAfterCompletion(status, TransactionSynchronization.STATUS_COMMITTED);
}
} finally {
// Clean up after completion, clearing synchronization if necessary,
// and invoking doCleanupAfterCompletion.
cleanupAfterCompletion(status);
}
}
private void cleanupAfterCompletion(DefaultTransactionStatus status) {
status.setCompleted();
if (status.isNewSynchronization()) {
TransactionSynchronizationManager.clear();
}
if (status.isNewTransaction()) {
// 这里主要做以下事情:
// 1. Remove the connection holder from the thread, if exposed.
// 2. Reset connection.
// 3. Release/close JDBC connection.
// 4. Clear the transactional state of this resource holder.
doCleanupAfterCompletion(status.getTransaction());
}
// 这里是恢复之前被挂起的事务
if (status.getSuspendedResources() != null) {
Object transaction = (status.hasTransaction() ? status.getTransaction() : null);
resume(transaction, (SuspendedResourcesHolder) status.getSuspendedResources());
}
}
doCommit(status)方法
在执行该方法之前有一个status.isNewTransaction()的判断,即判断当前TransactionStatus是否是一个新事务。
通过之前的源码分析,可以知道在以下情况下才会创建新事务,即NewTransaction:
- 当前无事务,目标方法为REQUIRED/REQUIRES_NEW/NESTED类型
- 当前有事务,目标方法为REQUIRES_NEW类型
看一下DataSourceTransactionManager的实现:
protected void doCommit(DefaultTransactionStatus status) {
DataSourceTransactionObject txObject = (DataSourceTransactionObject) status.getTransaction();
Connection con = txObject.getConnectionHolder().getConnection();
try {
con.commit();
} catch (SQLException ex) {
throw new TransactionSystemException("Could not commit JDBC transaction", ex);
}
}
代码很朴实无华,不需要过多的解释。
回滚事务
入口
completeTransactionAfterThrowing(txInfo, ex);
completeTransactionAfterThrowing方法
protected void completeTransactionAfterThrowing(@Nullable TransactionInfo txInfo, Throwable ex) {
if (txInfo != null && txInfo.getTransactionStatus() != null) {
// txInfo.transactionAttribute.rollbackOn(ex)在判断出现的异常是否需要回滚事务
// 这里面先判断异常是否匹配了rollbackFor和noRollbackFor配置
// 如果匹配了,就使用这两个配置确定是否需要回滚
// 否则就判断(ex instanceof RuntimeException || ex instanceof Error)来确定是否需要回滚
if (txInfo.transactionAttribute != null && txInfo.transactionAttribute.rollbackOn(ex)) {
try {
txInfo.getTransactionManager().rollback(txInfo.getTransactionStatus());
} catch (TransactionSystemException ex2) {
ex2.initApplicationException(ex);
throw ex2;
} catch (RuntimeException | Error ex2) {
throw ex2;
}
} else {
// 事务提交的逻辑之前看过
// We don't roll back on this exception.
// Will still roll back if TransactionStatus.isRollbackOnly() is true.
try {
txInfo.getTransactionManager().commit(txInfo.getTransactionStatus());
} catch (TransactionSystemException ex2) {
ex2.initApplicationException(ex);
throw ex2;
} catch (RuntimeException | Error ex2) {
throw ex2;
}
}
}
}
rollback事务
processRollback方法里面有一些细节需要特殊说明一下,这些细节可能会颠覆我们以往的对spring-tx的认知。
public final void rollback(TransactionStatus status) throws TransactionException {
if (status.isCompleted()) {
throw new IllegalTransactionStateException("");
}
DefaultTransactionStatus defStatus = (DefaultTransactionStatus) status;
processRollback(defStatus, false);
}
private void processRollback(DefaultTransactionStatus status, boolean unexpected) {
try {
boolean unexpectedRollback = unexpected;
try {
triggerBeforeCompletion(status);
if (status.hasSavepoint()) {
// 处理有保存点的事务即NESTED类型
status.rollbackToHeldSavepoint();
} else if (status.isNewTransaction()) {
// 新事务的回滚
// 处理REQUIRED、REQUIRES_NEW类型
doRollback(status);
} else {
// Participating in larger transaction
// 处理SUPPORTS、REQUIRED和MANDATORY类型
if (status.hasTransaction()) {
if (status.isLocalRollbackOnly() || isGlobalRollbackOnParticipationFailure()) {
doSetRollbackOnly(status);
} else {
// debug log
}
} else {
// debug log
}
// Unexpected rollback only matters here if we're asked to fail early
if (!isFailEarlyOnGlobalRollbackOnly()) {
unexpectedRollback = false;
}
}
} catch (RuntimeException | Error ex) {
triggerAfterCompletion(status, TransactionSynchronization.STATUS_UNKNOWN);
throw ex;
}
triggerAfterCompletion(status, TransactionSynchronization.STATUS_ROLLED_BACK);
// 如果SUPPORTS、REQUIRED和MANDATORY类型的嵌套方法出现了异常,这里会抛出一个异常
// Raise UnexpectedRollbackException if we had a global rollback-only marker
if (unexpectedRollback) {
throw new UnexpectedRollbackException(
"Transaction rolled back because it has been marked as rollback-only");
}
} finally {
// Clean up after completion, clearing synchronization if necessary,
// and invoking doCleanupAfterCompletion.
cleanupAfterCompletion(status);
}
}
NESTED的回滚
public void rollbackToHeldSavepoint() throws TransactionException {
Object savepoint = getSavepoint();
if (savepoint == null) {
throw new TransactionUsageException("");
}
// 将数据回滚到方法执行之前的保存点
getSavepointManager().rollbackToSavepoint(savepoint);
// 释放保存点
getSavepointManager().releaseSavepoint(savepoint);
setSavepoint(null);
}
// getSavepointManager().rollbackToSavepoint(savepoint)
public void rollbackToSavepoint(Object savepoint) throws TransactionException {
ConnectionHolder conHolder = getConnectionHolderForSavepoint();
try {
conHolder.getConnection().rollback((Savepoint) savepoint);
conHolder.resetRollbackOnly();
} catch (Throwable ex) {
throw new TransactionSystemException("Could not roll back to JDBC savepoint", ex);
}
}
// getSavepointManager().releaseSavepoint(savepoint)
public void releaseSavepoint(Object savepoint) throws TransactionException {
ConnectionHolder conHolder = getConnectionHolderForSavepoint();
try {
conHolder.getConnection().releaseSavepoint((Savepoint) savepoint);
} catch (Throwable ex) {
logger.debug("Could not explicitly release JDBC savepoint", ex);
}
}
新事务的回滚
protected void doRollback(DefaultTransactionStatus status) {
DataSourceTransactionObject txObject = (DataSourceTransactionObject) status.getTransaction();
Connection con = txObject.getConnectionHolder().getConnection();
try {
con.rollback();
} catch (SQLException ex) {
throw new TransactionSystemException("Could not roll back JDBC transaction", ex);
}
}
代码很朴实无华,不需要过多的解释。
SUPPORTS、REQUIRED和MANDATORY的回滚
// Participating in larger transaction
if (status.hasTransaction()) {
if (status.isLocalRollbackOnly() || isGlobalRollbackOnParticipationFailure()) {
// 如果SUPPORTS、REQUIRED和MANDATORY类型的嵌套方法出现了异常,需要回滚整个全局事务
doSetRollbackOnly(status);
} else {
// ...
}
} else {
// ...
}
// Unexpected rollback only matters here if we're asked to fail early
if (!isFailEarlyOnGlobalRollbackOnly()) {
// 这个变量的值只有这里有修改,所以如果代码执行不到这里,就意味着方法参数是什么,这个变量的值就是什么
unexpectedRollback = false;
}
processRollback有三处调用,只有一处unexpectedRollback传递的是true,在提交事务的代码里面,之前看到过,不过那个时候不明白是做什么的,分析到这里才知道了这个步骤的作用:
public final void commit(TransactionStatus status) throws TransactionException {
DefaultTransactionStatus defStatus = (DefaultTransactionStatus) status;
if (defStatus.isLocalRollbackOnly()) {
processRollback(defStatus, false);
return;
}
if (!shouldCommitOnGlobalRollbackOnly() && defStatus.isGlobalRollbackOnly()) {
// 这里传递的是true
// 即嵌套方法出现异常,且这个方法是SUPPORTS、REQUIRED和MANDATORY类型
// 需要回滚整个事务
// 此处的globalRollbackOnly的值是在doSetRollbackOnly(status)这行代码设置的
processRollback(defStatus, true);
return;
}
processCommit(defStatus);
}
如果SUPPORTS、REQUIRED和MANDATORY类型的嵌套方法出现了异常,这里会抛出一个异常:
if (unexpectedRollback) {
throw new UnexpectedRollbackException(
"Transaction rolled back because it has been marked as rollback-only");
}
一个示例:
@Transactional
void a() {
// db操作
// ...
try {
b();
} catch(Exception e) {
}
}
@Transactional
void b() {
// db操作
// ...
int i = 10 / 0;
}
上面示例的结果是a、b两个方法的所有操作都会被回滚,而且会抛出一个UnexpectedRollbackException异常,原因就是本小节中源代码。
事务的传播机制 - Propagation
REQUIRED(默认的事务传播类型)
Support a current transaction, create a new one if none exists.
如果当前没有事务,则自己新建一个事务,如果当前存在事务,则加入这个事务。
public void testMain(){
A(a1);
testB();
}
@Transactional(propagation = Propagation.REQUIRED)
public void testB(){
B(b1);
throw Exception;
B(b2);
}
SUPPORTS
Support a current transaction, execute non-transactionally if none exists.
当前存在事务,则加入当前事务,如果当前没有事务,就以非事务方法执行。
public void testMain(){
A(a1);
testB();
}
@Transactional(propagation = Propagation.SUPPORTS)
public void testB(){
B(b1);
throw Exception;
B(b2);
}
// a1和b1存入数据库,b2没有存入数据库
MANDATORY
Support a current transaction, throw an exception if none exists.
当前存在事务,则加入当前事务,如果当前事务不存在,则抛出异常。
public void testMain(){
A(a1);
testB();
}
@Transactional(propagation = Propagation.MANDATORY)
public void testB(){
B(b1);
throw Exception;
B(b2);
}
// a1存储成功,而b1和b2没有存储
REQUIRES_NEW
Create a new transaction, and suspend the current transaction if one exists.
创建一个新事务,如果存在当前事务,则挂起该事务。
@Transactional(propagation = Propagation.REQUIRED)
public void testMain(){
A(a1);
testB();
throw Exception;
}
@Transactional(propagation = Propagation.REQUIRES_NEW)
public void testB(){
B(b1);
B(b2);
}
// a1没有存储,而b1和b2存储成功
NOT_SUPPORTED
Execute non-transactionally, suspend the current transaction if one exists.
始终以非事务方式执行,如果当前存在事务,则挂起当前事务。
@Transactional(propagation = Propagation.REQUIRED)
public void testMain(){
A(a1);
testB();
}
@Transactional(propagation = Propagation.NOT_SUPPORTED)
public void testB(){
B(b1);
throw Exception;
B(b2);
}
// a1和b2没有存储,而b1存储成功
NEVER
Execute non-transactionally, throw an exception if a transaction exists.
不使用事务,如果当前事务存在,则抛出异常。
@Transactional(propagation = Propagation.REQUIRED)
public void testMain(){
A(a1);
testB();
}
@Transactional(propagation = Propagation.NEVER)
public void testB(){
B(b1);
B(b2);
}
// 抛出事务异常,且不会有数据存储到数据库
NESTED
Execute within a nested transaction if a current transaction exists, behave like REQUIRED otherwise.
如果当前事务存在,则在嵌套事务中执行,否则REQUIRED的操作一样(开启一个事务)。
和REQUIRES_NEW的区别: REQUIRES_NEW是新建一个事务并且新开启的这个事务与原有事务无关,而NESTED则是当前存在事务时(我们把当前事务称之为父事务)会开启一个嵌套事务(称之为一个子事务)。在NESTED情况下父事务回滚时,子事务也会回滚,而在REQUIRES_NEW情况下,原有事务回滚,不会影响新开启的事务。
和REQUIRED的区别:REQUIRED情况下,调用方存在事务时,则被调用方和调用方使用同一事务,那么被调用方出现异常时,由于共用一个事务,所以无论调用方是否catch其异常,事务都会回滚。而在NESTED情况下,被调用方发生异常时,调用方可以catch其异常,这样只有子事务回滚,父事务不受影响。
示例1:
@Transactional(propagation = Propagation.REQUIRED)
public void testMain(){
A(a1);
testB();
throw Exception;
}
@Transactional(propagation = Propagation.NESTED)
public void testB(){
B(b1);
B(b2);
}
// 所有数据都不会存入数据库,因为在testMain发生异常时,父事务回滚则子事务也跟着回滚了
示例2:
@Transactional(propagation = Propagation.REQUIRED)
public void testMain(){
A(a1);
try{
testB();
}catch(Exception e){
}
A(a2);
}
@Transactional(propagation = Propagation.NESTED)
public void testB(){
B(b1);
throw Exception;
B(b2);
}
// a1和a2存储成功,b1和b2存储失败