Spring七大事务传播特性
前言
Spring 的框架提供了事务管理的机制,让我可以通过@Transactional注解实现事务管理,其涉及到了Spring为了实现事务而提供的七大传播特性,不同的传播特性会有不一样的事务效果。
七大传播特性
在Spring框架中,Spring-tx提供了事务管理的基本功能。
maven
在Spring boot 项目中,可以引入Spring的事务管理,通过maven可以实现:
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>${version}</version>
</dependency>
然后在需要代理的方法上加上@Transactional注解,然后指定事务信息即可
@Service
public class TestService {
@Transactional(rollbackFor = Exception.class)
public void test(){}
}
传播特性
当使用@Transational注解的时候,可以指明Propagation,默认是Require。
在Spring-tx的org.springframework.transaction.annotation包下,Propagation声明了7中事务传播特性的枚举类,分别是
- Require
支持当前事务,如果当前事务不存在,则创建一个新的事务。即当前有事务,就是用当前事务,如果当前没有事务,就新建一个新的事务。 - Require_new
支持当前事务,如果当前存在当前事务,新建一个新的事务,并挂起当前事务。 - Support
如果当前有事务,就以当前事务执行,如果没有事务,就按照没有事务的方式执行。 - Not_Support
如果当前没有事务,就以非事务的方式执行,如果有事务,就挂起当前事务。 - Mandatory(强制的意思)
如果当前存在事务,就加入当前事务,如果没有事务,则报异常。 - Never
以非事务方式执行,如果存在事务,就抛出异常 - Nested
如果当前存在事务,则嵌套事务,如果不存在,就按照Require属性进行。
源码解读
当我们使用事务的时候,调用的方式,其实以动态代理的方式去执行当前的方法。
然后执行TransactionInterceptor的invoke()的方法:
@Override
@Nullable
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);
}
然后调用TransactionInterceptor的父类TransactionAspectSupport的方法invokeWithinTransaction():
这里摘取重要的代码片段
/**第一部分 **/
// If the transaction attribute is null, the method is non-transactional.
//获取事务属性源对象
TransactionAttributeSource tas = getTransactionAttributeSource();
//通过事务属性源对象获取到当前方法的事务属性信息
final TransactionAttribute txAttr = (tas != null ? tas.getTransactionAttribute(method, targetClass) : null);
//获取配置的事务管理器对象
final TransactionManager tm = determineTransactionManager(txAttr);
这段代码,获取的是事务的相关信息,包括事务的属性、事务管理器等
/**第二部分**/
PlatformTransactionManager ptm = asPlatformTransactionManager(tm);
//获取连接点的唯一标识,类名+方法名
final String joinpointIdentification = methodIdentification(method, targetClass, txAttr);
//声明式事务处理
if (txAttr == null || !(ptm instanceof CallbackPreferringPlatformTransactionManager)) {
// Standard transaction demarcation with getTransaction and commit/rollback calls.
//创建TransactionInfo对象,包括处理事务传播特性
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);
}
这段代码会把事务相关的信息处理完,核心处理事务传播特性的是
//创建TransactionInfo对象,包括处理事务传播特性
TransactionInfo txInfo = createTransactionIfNecessary(ptm, txAttr, joinpointIdentification);
处理完之后,会把事务信息封装成一个TransactionInfo实体返回。
/**第三部分**/
//成功后事务提交,恢复线程私有的老的事务信息
commitTransactionAfterReturning(txInfo);
处理事务传播特性createTransactionIfNecessary()的核心代码:
if (txAttr != null) {
f (tm != null) {
//处理传播特性,并返回一个TransactionInfo对象
status = tm.getTransaction(txAttr);
}else {
if (logger.isDebugEnabled()) {
logger.debug("Skipping transactional joinpoint [" + joinpointIdentification +
"] because no transaction manager has been configured");
}
}
}
然后在AbstractPlatformTransactionManager的getTransaction()方法中处理传播特性:
@Override
public final TransactionStatus getTransaction(@Nullable TransactionDefinition definition)
throws TransactionException {
// Use defaults if no transaction definition given.
//如果没有定义事务,则使用默认的
TransactionDefinition def = (definition != null ? definition : TransactionDefinition.withDefaults());
//获取事务,包括连接持有期,是否支持嵌套等
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.
//当前没有事务,如果事务的传播特性是mandatory,则抛出异常
if (def.getPropagationBehavior() == TransactionDefinition.PROPAGATION_MANDATORY) {
throw new IllegalTransactionStateException(
"No existing transaction found for transaction marked with propagation 'mandatory'");
}
//否则,如果是required、requires_new、nested的话,则新建事务
else if (def.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRED ||
def.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRES_NEW ||
def.getPropagationBehavior() == TransactionDefinition.PROPAGATION_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;
}
}
//以下是supports、not_supported、never三种,这三种,都是不使用事务的
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);
}
}
基本步骤是:没有定义事务就是用默认事务->通过获取数据库连接获取事务->判断是否有事务->根据是否有事务分别处理
有事务
当前有事务的时候,会调用handleExistingTransaction()方法进行处理:
/**
* Create a TransactionStatus for an existing transaction.
* 从已经存在的事务创建一个事务状态
*
*/
private TransactionStatus handleExistingTransaction(
TransactionDefinition definition, Object transaction, boolean debugEnabled)
throws TransactionException {
//如果传播级别是never,由于当前存在事务,则直接抛出异常
if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NEVER) {
throw new IllegalTransactionStateException(
"Existing transaction found for transaction marked with propagation 'never'");
}
//如果事务传播特性是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);
}
//如果传播特性是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 {
//并创建一个新的事务
return startTransaction(definition, transaction, debugEnabled, suspendedResources);
}
catch (RuntimeException | Error beginEx) {
resumeAfterBeginException(transaction, suspendedResources, beginEx);
throw beginEx;
}
}
//如果传播特性是nested
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()) {
//在一个已存在的Spring-managed事务内创建一个保存点,
//使用事务状态通过保存点管理器的api实现
//通常使用jdbc3.0的保存点,
// 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.
//可能是supports,也可能是require这两种传播特性
//由于这里处理的是,当前有事务,所以,基于这种情况下,require和support都是使用当前事务
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);
}
基本思路就是:
- 如果设置的传播特性是never,那么就抛出异常
- 如果设置的传播特性是not_support,那么就挂起当前事务
- 如果设置的传播特性是require_new,那么就挂起当前事务,并新建一个事务
- 如果设置的传播特性是nested,首先判断是否支持嵌套,不支持就抛出异常,然后设置一个保存点,并返回保存点
- 然后如果是require或者support,那么就使用当前事务
没有事务
- 如果设置的传播特性是Mandatory的,那么抛出异常
- 如果设置的传播特性是require_new、require、nested的,则新建一个事务
- 如果设置的传播特性是support、not_support、never的,则按照非事务的方式运行。
总结
- 两个require
require:有则使用,没有则新建
require_new:没有则新建一个,有则挂起,并新建一个 - 两个support
support:有则使用,没有则非事务
not_support:不支持事务,事务就挂起 - 两个异常
never:有事务,抛异常,没有事务,非事务进行
Mandatory:没有事务,抛异常,有事务,则使用当前事务 - 一个嵌套
有事务就嵌套,没有就新建一个