Spring之@Transactional核心源码解读

本文深入探讨了Spring的事务管理,包括事务的概念、ACID原则、Spring的事务支持,重点解析了@Transactional注解的源码实现,从开启事务、处理异常回滚到提交事务的过程,并给出了使用Spring事务管理的注意事项。

前言

在基于Spring框架的程序中我们一般会使用Spring提供的事务管理器对事务进行管理。Spring支持编程式事务以及声明式事务,声明式事务使用@Transactional注解标志方法,表示开启事务,使用注解较为简洁、方便,也是Spring中较常用的开启事务的方式,为了能灵活使用@Transactional注解,有必要对该注解的实现深入了解。

通篇文章由介绍事务开启,再逐步过渡到Spring对事务的支持,以及如何使用Spring管理事务,之后再深入介绍@Transactional注解的核心源码,最后以讲解@Transactional注解使用的注意事项完结整篇文章。

事务的概念

事务是由不可分割的一系列操作组成的工作单元,这些操作紧密相连、密不可分,要么同时执行成功,要么同时执行失败。

事务遵循ACID原则:

  1. A(Atomicity):原子性,在开启事务的前提下,操作执行的过程中,任何一个操作失败都会导致事务执行失败。
  2. C(Consistency):一致性,事务的执行结果总是使得数据由一个一致性的状态转变为另一个一致性的状态。
  3. I(Isolation):隔离性,在多个事务开启的前提下,多个事务同时执行不会相互造成影响。
  4. D(Durability):持久性,事务执行成功后,对数据状态造成的改变是永久的,不会因为机器发生故障等其他问题而造成数据丢失。

事务的作用

上一段简单的介绍了事务的概念,那程序中为什么需要使用事务呢?接下来将从事务遵循的ACID原则展开讲述事务在程序中的作用。

举一个常用的银行转账例子:

账户A、账户B分别有2000元、5000元存款,账户A向账户B转账1000元,这个动作从开始到最终完成大致需要经过以下几个步骤:

  1. 检查账户A余额是否大于2000
  2. 从账户A扣除1000元
  3. 将1000元转入账户B

原子性

试想一下转账流程未开启事务,在执行的过程中,账户A成功扣除1000元后,账户B还未被转入1000元,此时系统发生了故障,就可能会引发一个问题,账户A已经成功扣除了1000元,但账户B未入账,最终导致1000元不翼而飞。

每个系统都不是十全十美的,我们无法预料系统什么何时回发生故障,但我们能做的就是在事故发生时,我们的系统拥有能应对事故的能力,这次消失的1000元是由于未保障原子性导致的。没有保障的系统会引发用户的信任危机,最终使得系统被抛弃,甚至使得业务走向失败。转账这个功能是一个完整的业务,这个业务下的所有操作应该保持一致的执行结果要么一同成功,要么一同失败。

一致性

账户A向账户B转账3000元,但账户A只有2000元,在大众的认知范围内银行账户余额是不允许为负数的,所以这次转账最终应是失败的,如果出现了账户余额负数的情况,这就破坏了事务的一致性,符合事务的工作单元需要保证一致性。

隔离性

现代的程序大都是支持并发运行的,就会出现多个方法同时执行的情况,如线程1操作账户A向账户B转账1000元,同一时间线程2也操作账户C向账户B转账1000元,线程1与线程2进行运算时拿到的账户B的余额都是5000元,两个线程运算最终结果都是账户B的余额是6000元,落到库中账户B的最终余额就是6000元,但实际上账户A和C都向B转1000元,账户B应该是7000元的,消失的1000元去哪了呢?这就是未保障隔离性可能发生的后果,多线程并发操作数据库未开启事务,没有隔离性作保障,最终的结果会引发很多问题。

持久性

账户A向账户B成功转账1000元后,账户A的余额为1000元,账户B的余额为6000元,这个状态是持久的,无论是否数据库宕机,还是发生其他的故障,这个状态都不会变。

Spring对事务的支持

Spring并不直接管理事务,而是提供了三个核心接口:PlatformTransactionManager、TransactionDefinition、TransactionDefinition,供各个ORM平台实现个性化的管理事务的方式。

同时Spring为我们提供了两种方式使用事务:编程式事务管理功能、声明式事务管理功能。编程式事务与声明式事务相比较,编程式事务对代码有侵入性,而声明式事务使用起来简便,只需要编写少量与事务管理相关的代码,并与业务代码相分离无耦合,但声明式事务能实现最细粒度的事务管理级别是方法级的,需要更细粒度只能使用编程式事务。

核心接口:

PlatformTransactionManager

PlatformTransactionManager接口为我们提供了三个方法:

public interface PlatformTransactionManager extends TransactionManager {

    // 根据事务的定义创建事务,并返回事务当前的状态
    TransactionStatus getTransaction(@Nullable TransactionDefinition definition) throws TransactionException;

    // 根据事务状态提交事务
    void commit(TransactionStatus status) throws TransactionException;

    // 根据事务状态回滚事务
    void rollback(TransactionStatus status) throws TransactionException;

}

Spring并不直接管理事务,而是提供了统一的PlatformTransactionManager接口,下图是展示了PlatformTransactionManager部分子类,各个ORM平台通过实现该接口提供具体的事务管理机制,如jdbc与iBatis提供的该接口实现类为DataSourceTransactionManager。

TransactionDefinition

TransactionDefinition是事务的定义,包含了事务常用的属性,包括事务的传播行为、隔离级别、事务超时时间。Spring根据TransactionDefinition创建事务。

public interface TransactionDefinition {

    // 事务传播行为
    default int getPropagationBehavior() {
        return PROPAGATION_REQUIRED;
    }

    // 事务隔离级别
    default int getIsolationLevel() {
        return ISOLATION_DEFAULT;
    }

    // 事务超时时间
    default int getTimeout() {
        return TIMEOUT_DEFAULT;
    }

    // 事务只读状态
    default boolean isReadOnly() {
        return false;
    }

    // 事务名称
    @Nullable
    default String getName() {
        return null;
    }

}

TransactionStatus

TransactionStatus记录了事务运行的状态,包括当前事务是否新事物,是否有保存点,是否被标记为rollback-only。

public interface TransactionStatus extends SavepointManager, Flushable {

    // 是否新事物
    boolean isNewTransaction();

    // 是否内部存在保存点
    boolean hasSavepoint();

    // 将事物标记为回滚
    void setRollbackOnly();

    // 是否事物被标记为rollback-only
    boolean isRollbackOnly();

    // 将底层的会话刷新至数据库
    @Override
    void flush();

    // 事物是否完成,指事物是否已经提交或回滚
    boolean isCompleted();

}

TransactionStatus实现了SavepointManager接口,SavepointManager包含了操作savepoint的三个方法

public interface SavepointManager {
    
    // 创建保存点,后续可以调用rollbackToSavepoint()回滚到标记的保存点
    Object createSavepoint() throws TransactionException;

    // 回滚保存点
    void rollbackToSavepoint(Object savepoint) throws TransactionException;

    // 释放指定的savepoint保存点,
    void releaseSavepoint(Object savepoint) throws TransactionException;

}

事务的创建、回滚、提交都是基于该TransactionStatus接口完成。

两种事务管理方式

使用编程式事务管理

  1. 通过PlatformTransactionManager控制事务,需要手动执行回滚或提交事务
@Configuration
public class AppConfig {
    @Bean
    public DataSource dataSource(){
        DataSource dataSource = new DataSource();
        dataSource.setDriverClassName("driverClassName");
        dataSource.setUrl("url");
        dataSource.setUsername("username");
        dataSource.setPassword("password");
        return dataSource;
    }

    @Bean
    public PlatformTransactionManager transactionManager(DataSource dataSource) {
        return new DataSourceTransactionManager(dataSource);
    }
}
@Service
public class TestAServiceImpl implements TestAService {

    @Autowired
    private PlatformTransactionManager txManager;

    @Override
    public void test1() {
        DefaultTransactionDefinition def = new DefaultTransactionDefinition();
        def.setName("txName");
        def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);

        TransactionStatus status = txManager.getTransaction(def);
        try {
            // 业务逻辑
        }catch (MyException ex) {
            txManager.rollback(status);
            throw ex;
        }
        txManager.commit(status);
    }
}
  1. 通过TransactionTemplate控制事务,减少了手动关闭回滚代码
@Configuration
public class AppConfig {

    @Bean
    public DataSource dataSource(){
        DataSource dataSource = new DataSource();
        dataSource.setDriverClassName("driverClassName");
        dataSource.setUrl("url");
        dataSource.setUsername("username");
        dataSource.setPassword("password");
        return dataSource;
    }

    @Bean
    public PlatformTransactionManager transactionManager(DataSource dataSource) {
        return new DataSourceTransactionManager(dataSource);
    }

    @Bean
    public TransactionTemplate transactionTemplate(PlatformTransactionManager transactionManager) {
        return new TransactionTemplate(transactionManager);
    }
}
@Service
public class TestAServiceImpl implements TestAService {

    @Autowired
    private TransactionTemplate transactionTemplate;

    @Override
    public void test1() {
        // 无返回值
        transactionTemplate.execute(new TransactionCallbackWithoutResult() {
            @Override
            protected void doInTransactionWithoutResult(TransactionStatus status) {
                // 业务逻辑
            }
        });
        
        // 有返回值
        Object object = transactionTemplate.execute(new TransactionCallback<Object>() {
            @Override
            public Object doInTransaction(TransactionStatus status) {
                // 业务逻辑
                return ...;
            }
        });
    }
}

使用声明式事务管理

使用@Transactional注解开启事务,底层基于AOP实现,在执行目标方法前创建或加入一个事务,目标方法执行后关闭或提交事务。

spring.datasource.username=username
spring.datasource.password=password
spring.datasource.url=url
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
@Transactional(rollbackFor = Exception.class)
@Override
public void test1() {
    // 业务逻辑
}

从以上两种事务管理方式的使用可以看出,声明式事务使用特别简洁,几乎没有冗余的代码,只需要一行代码。但编程事务可以实现较方法级别更细粒度的管理

@Transactional注解源码解读

在Spring中,较常用@Transactional注解操作数据库事务,该方式基于Spring AOP实现,而Spring AOP底层原理是动态代理。Spring AOP将与业务代码无关且逻辑相同的重复代码抽离,并使用动态代理的方式将重复代码与业务方法融合,从而实现对原有接口添加额外功能,却又不影响现有对象功能。

对SpringAOP有了解的同学都清楚,使用SpringAOP需要定义切点,@Transactional注解标明方法为植入点,植入事务,Spring会拦截被@Transactional注解的方法,并由TransactionInterceptor的invoke方法对业务方法实现增强。

注:以下源代码解读过程中,调用需要PlatformTransactionManager的实现类实现的方法时,都默认解读实现类为DataSourceTransactionManager的方法

@Override
@Nullable
public Object invoke(MethodInvocation invocation) throws Throwable {
    Class<?> targetClass = (invocation.getThis() != null ? AopUtils.getTargetClass(invocation.getThis()) : null);

    return invokeWithinTransaction(invocation.getMethod(), targetClass, invocation::proceed);
}

@Nullable
protected Object invokeWithinTransaction(Method method, @Nullable Class<?> targetClass,
        final InvocationCallback invocation) throws Throwable {

    TransactionAttributeSource tas = getTransactionAttributeSource();
        // 获取事务的定义
    final TransactionAttribute txAttr = (tas != null ? tas.getTransactionAttribute(method, targetClass) : null);
    // 从beanFactory获取PlatformTransactionManager的实现
    final PlatformTransactionManager tm = determineTransactionManager(txAttr);
    // 获取类方法的唯一标识
        final String joinpointIdentification = methodIdentification(method, targetClass, txAttr);

    if (txAttr == null || !(tm instanceof CallbackPreferringPlatformTransactionManager)) {
        // 开启事务,创建TransactionInfo
        TransactionInfo txInfo = createTransactionIfNecessary(tm, txAttr, joinpointIdentification);

        Object retVal;
        try {
            // 执行业务方法
            retVal = invocation.proceedWithInvocation();
        } catch (Throwable ex) {
            // 异常回滚事务
            completeTransactionAfterThrowing(txInfo, ex);
            throw ex;
        } finally {
            // 重置线程事务信息
            cleanupTransactionInfo(txInfo);
        }
        // 提交事务
        commitTransactionAfterReturning(txInfo);
        return retVal;
    }
        ...
}

开启事务前准备

获取事务的定义

TransactionAttributeSource的getTransactionAttribute方法返回TransactionAttribute,TransactionAttribute继承了TransactionDefinition,TransactionDefinition在上文介绍过是事务的定义,包含事务的常用属性,TransactionAttribute是对TransactionDefinition的扩展,允许根据异常回滚。

// 获取事务的定义
final TransactionAttribute txAttr = (tas != null ? tas.getTransactionAttribute(method, targetClass) : null);

获取PlatformTransactionManager实现类

// 从beanFactory获取PlatformTransactionManager的实现
final PlatformTransactionManager tm = determineTransactionManager(txAttr);
@Nullable
protected PlatformTransactionManager determineTransactionManager(@Nullable TransactionAttribute txAttr) {
        ...
        PlatformTransactionManager defaultTransactionManager = getTransactionManager();
    if (defaultTransactionManager == null) {
        defaultTransactionManager = this.transactionManagerCache.get(DEFAULT_TRANSACTION_MANAGER_KEY);
        if (defaultTransactionManager == null) {
            // 从bean工厂中获取实际注册的PlatformTransactionManager,jdbc返回DataSourceTransactionManager
            defaultTransactionManager = this.beanFactory.getBean(PlatformTransactionManager.class);
            this.transactionManagerCache.putIfAbsent(
                    DEFAULT_TRANSACTION_MANAGER_KEY, defaultTransactionManager);
        }
    }
    return defaultTransactionManager;
        ...
}

开启事务

TransactionInfo的内容包含事务相关信息,如PlatformTransactionManager、TransactionStatus、TransactionAttribute等

// 开启事务,创建TransactionInfo
TransactionInfo txInfo = createTransactionIfNecessary(tm, txAttr, joinpointIdentification);

createTransactionIfNecessary方法执行步骤:

  1. 获取事务
  2. 将事物绑定至线程
protected TransactionInfo createTransactionIfNecessary(@Nullable PlatformTransactionManager tm,
        @Nullable TransactionAttribute txAttr, final String joinpointIdentification) {

    // 未明确事务名称,将方法唯一标识作为事务名称
    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) {
            status = tm.getTransaction(txAttr);
        }
        else {
            if (logger.isDebugEnabled()) {
                logger.debug("Skipping transactional joinpoint [" + joinpointIdentification +
                        "] because no transaction manager has been configured");
            }
        }
    }
    // 将事务绑定至线程
    return prepareTransactionInfo(tm, txAttr, joinpointIdentification, status);
}

getTransaction方法根据事务定义生成事务

@Override
public final TransactionStatus getTransaction(@Nullable TransactionDefinition definition) throws TransactionException {
    // 创建事务,设置事务的数据库连接。使用模板方法,由AbstractPlatformTransactionManager的实现类实现该方法
    Object transaction = doGetTransaction();

    boolean debugEnabled = logger.isDebugEnabled();

    if (definition == null) {
        // 无事务定义,使用默认的定义
        definition = new DefaultTransactionDefinition();
    }


    // 处理已存在的事务的情况
    if (isExistingTransaction(transaction)) {
        return handleExistingTransaction(definition, transaction, debugEnabled);
    }

    if (definition.getTimeout() < TransactionDefinition.TIMEOUT_DEFAULT) {
        throw new InvalidTimeoutException("Invalid transaction timeout", definition.getTimeout());
    }

    // 上文已调用isExistingTransaction方法判断过是否存在事务,存在事务会进入handleExistingTransaction方法,执行完会return,走到此处说明不存在事务,PROPAGATION_MANDATORY定义不存在事务会抛出异常
    if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_MANDATORY) {
        throw new IllegalTransactionStateException(
                "No existing transaction found for transaction marked with propagation 'mandatory'");
    }
    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 | Error ex) {
            resume(null, suspendedResources);
            throw ex;
        }
    }
    ...
}

handleExistingTransaction处理存在事务

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) {
        if (debugEnabled) {
            logger.debug("Suspending current transaction");
        }
        // 挂起事务,会清除当前线程所持有的事务信息
        Object suspendedResources = suspend(transaction);
        boolean newSynchronization = (getTransactionSynchronization() == SYNCHRONIZATION_ALWAYS);
        return prepareTransactionStatus(
                definition, null, false, newSynchronization, debugEnabled, suspendedResources);
    }

    // 传播机制PROPAGATION_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 {
            boolean newSynchronization = (getTransactionSynchronization() != SYNCHRONIZATION_NEVER);
            DefaultTransactionStatus status = newTransactionStatus(
                    definition, transaction, true, newSynchronization, debugEnabled, suspendedResources);
            doBegin(transaction, definition);
            prepareSynchronization(status, definition);
            return status;
        }
        catch (RuntimeException | Error beginEx) {
            resumeAfterBeginException(transaction, suspendedResources, beginEx);
            throw beginEx;
        }
    }

    // 传播机制PROPAGATION_NESTED,判断是否允许嵌入事务,默认不允许,不允许嵌入事务抛出异常,允许则在该处创建Savepoint,后续嵌套子事务可回滚至此位置不支持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'");
        }
        if (debugEnabled) {
            logger.debug("Creating nested transaction with name [" + definition.getName() + "]");
        }
        if (useSavepointForNestedTransaction()) {
            DefaultTransactionStatus status =
                    prepareTransactionStatus(definition, transaction, false, false, debugEnabled, null);
            status.createAndHoldSavepoint();
            return status;
        }
        else {
            boolean newSynchronization = (getTransactionSynchronization() != SYNCHRONIZATION_NEVER);
            DefaultTransactionStatus status = newTransactionStatus(
                    definition, transaction, true, newSynchronization, debugEnabled, null);
            doBegin(transaction, definition);
            prepareSynchronization(status, definition);
            return status;
        }
    }
        ...
    return prepareTransactionStatus(definition, transaction, false, newSynchronization, debugEnabled, null);
}

获取数据库连接

@Override
protected void doBegin(Object transaction, TransactionDefinition definition) {
    DataSourceTransactionObject txObject = (DataSourceTransactionObject) transaction;
    Connection con = null;

    try {
        if (!txObject.hasConnectionHolder() ||
                txObject.getConnectionHolder().isSynchronizedWithTransaction()) {
            Connection newCon = obtainDataSource().getConnection();
            if (logger.isDebugEnabled()) {
                logger.debug("Acquired Connection [" + newCon + "] for JDBC transaction");
            }
            // 配置数据库连接
            txObject.setConnectionHolder(new ConnectionHolder(newCon), true);
        }

        txObject.getConnectionHolder().setSynchronizedWithTransaction(true);
        con = txObject.getConnectionHolder().getConnection();

        // 设置事务默认隔离级别
        Integer previousIsolationLevel = DataSourceUtils.prepareConnectionForTransaction(con, definition);
        txObject.setPreviousIsolationLevel(previousIsolationLevel);

        // 数据库连接为自动提交,则关闭数据库连接的自动提交操作,同时设置mustRestoreAutoCommit=true,在当前事务执行完毕恢复数据库连接自动提交为true
        if (con.getAutoCommit()) {
            txObject.setMustRestoreAutoCommit(true);
            if (logger.isDebugEnabled()) {
                logger.debug("Switching JDBC Connection [" + con + "] to manual commit");
            }
            con.setAutoCommit(false);
        }

        // 数据库连接事务激活前的准备工作
        prepareTransactionalConnection(con, definition);
        // 设置激活事务标志为true
        txObject.getConnectionHolder().setTransactionActive(true);

        // 设置数据库连接的超时时间为用户定义的时间,用户未设置,则使用默认的超时时间
        int timeout = determineTimeout(definition);
        if (timeout != TransactionDefinition.TIMEOUT_DEFAULT) {
            txObject.getConnectionHolder().setTimeoutInSeconds(timeout);
        }

        // 将数据库连接绑定到线程,使用了ThreadLocal
        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);
    }
}

执行业务方法

// 执行业务方法
retVal = invocation.proceedWithInvocation();

处理异常回滚

// 异常回滚事务
completeTransactionAfterThrowing(txInfo, ex);
throw ex;

一旦业务方法在执行过程中发生异常,异常被抛出,将会被try..catch...捕获,completeTransactionAfterThrowing方法根据异常信息处理事务后,再将异常抛出进行后续操作

protected void completeTransactionAfterThrowing(@Nullable TransactionInfo txInfo, Throwable ex) {
    if (txInfo != null && txInfo.getTransactionStatus() != null) {
                ...
        // transactionAttribute中的rollbackOn方法判断抛出的异常符合回滚条件,将操作回滚事务
        if (txInfo.transactionAttribute != null && txInfo.transactionAttribute.rollbackOn(ex)) {
            try {
                // 操作PlatformTransactionManager的rollback方法回滚事务
                txInfo.getTransactionManager().rollback(txInfo.getTransactionStatus());
            }
                        ...
        }
        else {
            try {
                // transactionAttribute为空,或抛出的异常不在回滚条件范围内,操作提交事务
                txInfo.getTransactionManager().commit(txInfo.getTransactionStatus());
            }
                        ...
        }
    }
}

rollback方法

检查事务是否已完成,若事务已完成会抛出异常,不允许执行回滚操作,否则交由processRollback方法执行回滚操作

@Override
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, false);
}

processRollback方法

private void processRollback(DefaultTransactionStatus status, boolean unexpected) {
    try {
        boolean unexpectedRollback = unexpected;

        try {
            // 执行TransactionSynchronization.beforeCompletion方法,如果数据库连接不再使用,提前释放资源,并设置holderActive=false
            triggerBeforeCompletion(status);

            if (status.hasSavepoint()) {
                // 根据事务状态,判断存在savepoint,回滚到savepoint
                if (status.isDebug()) {
                    logger.debug("Rolling back transaction to savepoint");
                }
                status.rollbackToHeldSavepoint();
            }
            else if (status.isNewTransaction()) {
                if (status.isDebug()) {
                    logger.debug("Initiating transaction rollback");
                }
                // 独立的事务,操作回滚
                doRollback(status);
            }
            else {
                // 非独立事务,标记rollbackOnly=true,后续事务执行完毕再进行回滚
                if (status.hasTransaction()) {
                    if (status.isLocalRollbackOnly() || isGlobalRollbackOnParticipationFailure()) {
                        if (status.isDebug()) {
                            logger.debug("Participating transaction failed - marking existing transaction as rollback-only");
                        }
                        doSetRollbackOnly(status);
                    }
                    else {
                        if (status.isDebug()) {
                            logger.debug("Participating transaction failed - letting transaction originator decide on rollback");
                        }
                    }
                }
                else {
                    logger.debug("Should roll back transaction but cannot - no transaction available");
                }
                if (!isFailEarlyOnGlobalRollbackOnly()) {
                    unexpectedRollback = false;
                }
            }
        }
        catch (RuntimeException | Error ex) {
            triggerAfterCompletion(status, TransactionSynchronization.STATUS_UNKNOWN);
            throw ex;
        }

        // 执行TransactionSynchronization.afterCompletion方法,holderActive=true释放资源
        triggerAfterCompletion(status, TransactionSynchronization.STATUS_ROLLED_BACK);

        if (unexpectedRollback) {
            throw new UnexpectedRollbackException(
                    "Transaction rolled back because it has been marked as rollback-only");
        }
    }
    finally {
        // 标记当前事务执行完成,清除当前线程的事务信息,将挂起的事务恢复
        cleanupAfterCompletion(status);
    }
}

提交事务

// 提交事务
commitTransactionAfterReturning(txInfo);

如若未发生异常按正常流程提交事务,由commit方法实现实际的提交流程

protected void commitTransactionAfterReturning(@Nullable TransactionInfo txInfo) {
    if (txInfo != null && txInfo.getTransactionStatus() != null) {
        if (logger.isTraceEnabled()) {
            logger.trace("Completing transaction for [" + txInfo.getJoinpointIdentification() + "]");
        }
        // 调用PlatformTransactionManager的commit方法,提交事务
        txInfo.getTransactionManager().commit(txInfo.getTransactionStatus());
    }
}

commit方法

@Override
public final void commit(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");
    }

    // rollbackOnly=true,已标记为回滚,不进行提交,直接回滚
    DefaultTransactionStatus defStatus = (DefaultTransactionStatus) status;
    if (defStatus.isLocalRollbackOnly()) {
        if (defStatus.isDebug()) {
            logger.debug("Transactional code has requested rollback");
        }
        processRollback(defStatus, false);
        return;
    }

    if (!shouldCommitOnGlobalRollbackOnly() && defStatus.isGlobalRollbackOnly()) {
        if (defStatus.isDebug()) {
            logger.debug("Global transaction is marked as rollback-only but transactional code requested commit");
        }
        processRollback(defStatus, true);
        return;
    }

    // 执行回滚操作
    processCommit(defStatus);
}

processCommit方法

private void processCommit(DefaultTransactionStatus status) throws TransactionException {
    try {
        boolean beforeCompletionInvoked = false;

        try {
            boolean unexpectedRollback = false;
            prepareForCommit(status);
            triggerBeforeCommit(status);
            triggerBeforeCompletion(status);
            beforeCompletionInvoked = true;

            if (status.hasSavepoint()) {
                if (status.isDebug()) {
                    logger.debug("Releasing transaction savepoint");
                }
                unexpectedRollback = status.isGlobalRollbackOnly();
                // 存在savepoint,则清除savepoint
                status.releaseHeldSavepoint();
            }
            else if (status.isNewTransaction()) {
                if (status.isDebug()) {
                    logger.debug("Initiating transaction commit");
                }
                unexpectedRollback = status.isGlobalRollbackOnly();
                // 独立事务,则提交事务
                doCommit(status);
            }
            ...
}

以上流程是@Transactional注解实现的核心流程。Spring对事务的支持离不开PlatformTransactionManager、TransactionStatus、TransactionDefinition,由它们共同完成对事务的管理。

注意事项

使用Spring事务管理器前需检查存储引擎是否支持事务

应用程序是否支持事务,依赖于底层存储引擎是否支持事务。如接入的是MySQL,且使用的存储引擎是innodb,则程序支持事务,如使用的存储引擎是myisam,则不支持事务。

经过实践,得出结论底层存储引擎不支持事务,在程序中加入spring事务管理,程序不会抛出异常,为了防止业务正常运行建议在程序中使用spring事务管理之前先在数据库中执行如下语句,以检查所使用的存储引擎是否支持事务。

show table status from `database_name` where name='table_name';

类内部方法相互调用

内部方法相互调用不会走代理,所以子方法的事务不会生效。

@Transactional注解是基于SpringAOP的功能才得以实现对事务进行管理,在Spring的IoC容器初始化时,对管理的Bean会生成代理类,代理类将原类包装起来,对于使用了@Transactional的类,会在代理类中调用事务管理器。当实现@Transactional注解的方法由外部方法调用时,会被Spring拦截器拦截并走该方法的代理类,事务可以生效,而内部方法间相互调用,并不会被Spring拦截器拦截,走的是调用原类方法本身,因而事务不会起作用。

需要内部方法间相互调用事务起作用,可以使用如下三种方式:

  1. 使用编程式事务
  2. 将需要实现事务的方法都管理在一个类中
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值