spring事务源码分析

66 阅读2分钟

spring事务源码分析

1、事务如何生效?

@EnableTransactionManagement  事务是如何起作用的,通过代理对象执行方法。 ProxyTransactionManagementConfiguration 该类相当于给系统注入了一个事务的拦截器,通过拦截器来拦截是否需要支持事务。该类非常重要,对于事务的分析很有帮助。

2、事务执行的代码

import org.springframework.transaction.TransactionSystemException;

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

    // 如果transaction attribute为空,该方法就是非事务(非编程式事务)
    final TransactionAttribute txAttr = getTransactionAttributeSource().getTransactionAttribute(method, targetClass);
    final PlatformTransactionManager tm = determineTransactionManager(txAttr);
    final String joinpointIdentification = methodIdentification(method, targetClass, txAttr);
     // 标准声明式事务:如果事务属性为空 或者 非回调偏向的事务管理器
    if (txAttr == null || !(tm instanceof CallbackPreferringPlatformTransactionManager)) {
        // Standard transaction demarcation with getTransaction and commit/rollback calls.
        TransactionInfo txInfo = createTransactionIfNecessary(tm, txAttr, joinpointIdentification);
        Object retVal = null;
        try {
            // 这里就是一个环绕增强,在这个proceed前后可以自己定义增强实现
            // 方法执行
            retVal = invocation.proceedWithInvocation();
        }
        catch (Throwable ex) {
            // 根据事务定义的,该异常需要回滚就回滚,否则提交事务
            completeTransactionAfterThrowing(txInfo, ex);
            throw ex;
        }
        finally {//清空当前事务信息,重置为老的
            cleanupTransactionInfo(txInfo);
        }//返回结果之前提交事务
        commitTransactionAfterReturning(txInfo);
        return retVal;
    }
     // 编程式事务:(回调偏向)
        else {
        final ThrowableHolder throwableHolder = new ThrowableHolder();

        // It's a CallbackPreferringPlatformTransactionManager: pass a TransactionCallback in.
        try {
            Object result = ((CallbackPreferringPlatformTransactionManager) tm).execute(txAttr,
                    new TransactionCallback<Object>() {
                        @Override
                        public Object doInTransaction(TransactionStatus status) {
                            TransactionInfo txInfo = prepareTransactionInfo(tm, txAttr, joinpointIdentification, status);
                            try {
                                return invocation.proceedWithInvocation();
                            }
                            catch (Throwable ex) {// 如果该异常需要回滚
                                if (txAttr.rollbackOn(ex)) {
                                    // 如果是运行时异常返回
                                    if (ex instanceof RuntimeException) {
                                        throw (RuntimeException) ex;
                                    }// 如果是其它异常都抛ThrowableHolderException
                                    else {
                                        throw new ThrowableHolderException(ex);
                                    }
                                }// 如果不需要回滚
                                else {
                                    // 定义异常,最终就直接提交事务了
                                    throwableHolder.throwable = ex;
                                    return null;
                                }
                            }
                            finally {//清空当前事务信息,重置为老的
                                cleanupTransactionInfo(txInfo);
                            }
                        }
                    });

            // 上抛异常
            if (throwableHolder.throwable != null) {
                throw throwableHolder.throwable;
            }
            return result;
        }
        catch (ThrowableHolderException ex) {
            throw ex.getCause();
        }
        catch (TransactionSystemException ex2) {
            if (throwableHolder.throwable != null) {
                logger.error("Application exception overridden by commit exception", throwableHolder.throwable);
                ex2.initApplicationException(throwableHolder.throwable);
            }
            throw ex2;
        }
        catch (Throwable ex2) {
            if (throwableHolder.throwable != null) {
                logger.error("Application exception overridden by commit exception", throwableHolder.throwable);
            }
            throw ex2;
        }
    }
}

3、事务失效的几种原因

  • 数据库引擎不支持事务
  • 对象没有被Spring管理
  • 方法不是public的
  • 类内部自身调用问题
  • 数据源没有配置事务管理器
  • 主动声明不支持事务
  • 捕获了异常
  • 抛出的异常不适合
  • 切面引起的事务不生效

总结:

最有可能发生事务不生效的场景是: 类内部自身调用问题,捕获了异常