Spring源码解析(四)--Spring事务的底层源码解析

前文:今天我们主要来学习一下Spring事务的源码解析,主要讲的是Spring的申明式事务的讲解。申明式事务管理: 基于Spring AOP实现。其本质是对方法前后进行拦截,然后在目标方法开始之前创建或者加入一个事务,在执行完目标方法之后根据执行情况提交或者回滚事务。申明式事务管理不需要入侵代码,通过@Transactional就可以进行事务操作,且大部分业务都可以满足,推荐使用。

一、本篇幅介绍的接口和类。

1、@EnableTransactionManagement 申明式事务的启用注解,也是源码解析的入口。
2、TransactionManagementConfigurationSelector 事务管理配置导入选择器。
3、AutoProxyRegistrar:给容器中注册一个 InfrastructureAdvisorAutoProxyCreator 组件;利用后置处理器机制在对象创建以后,包装对象,返回一个代理对象(增强器),代理对象执行方法利用拦截器链进行调用。
4、ProxyTransactionManagementConfiguration:就是一个配置类,定义了事务增强器。
5、InfrastructureAdvisorAutoProxyCreator 一个BeanPostProcessor.class的子类,也就是后置处理器,它可以在Spring初始化bean之前或之后进行功能增强。
6、TransactionAttributeSource 事务注册解析器 。解析@Transactional()的里面的属性和传播行为。
7、TransactionInterceptor 事务拦截器,生成动态类后,执行目标方法时,进行拦截和调用链的执行。

二、源码解析入口。

(一)、注解EnableTransactionManagement

使用EnableTransactionManagement注解可以开启Spring事务,而EnableTransactionManagement源代码如下:

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(TransactionManagementConfigurationSelector.class)
public @interface EnableTransactionManagement {
 
    boolean proxyTargetClass() default false;
 
        /**
         *  默认是使用代理的通知模式
         */ 
    AdviceMode mode() default AdviceMode.PROXY;
 
    int order() default Ordered.LOWEST_PRECEDENCE;
 
}

了解TransactionManagementConfigurationSelector.class的功能:

(二)、TransactionManagementConfigurationSelector

该类实现了ImportSelector接口,通过覆写selectImports()方法,手动将java类注册到Spring框架的IOC容器中。

@Override
    protected String[] selectImports(AdviceMode adviceMode) {
        switch (adviceMode) {
            case PROXY:  // 默认就是Proxy模式
                return new String[] {AutoProxyRegistrar.class.getName(),ProxyTransactionManagementConfiguration.class.getName()};
            case ASPECTJ:
                return new String[] {determineTransactionAspectClass()};
            default:
                return null;
        }
    }

(三)、AutoProxyRegistrar

通过这个类,Spring会将InfrastructureAdvisorAutoProxyCreator.class注入到IOC容器,然后请看该类类图:
在这里插入图片描述
由图知InfrastructureAdvisorAutoProxyCreator.class是一个BeanPostProcessor.class的子类,理论上它可以在Spring初始化bean之前或之后进行功能增强,Sping框架原生选择是之后增强,具体的增强方法是在AbstractAutoProxyCreator#postProcessAfterInitialization()方法。进行包装增强。创建代理对象==

@Override
    public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
        if (bean != null) {
            Object cacheKey = getCacheKey(bean.getClass(), beanName);
            if (this.earlyProxyReferences.remove(cacheKey) != bean) {
                return wrapIfNecessary(bean, beanName, cacheKey);
            }
        }
        return bean;
    }

/**  Wrap the given bean if necessary  
  *  对bean进行包装,其实就是创建代理对象
  */
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
        
        // 省略。。。。
        // Create proxy if we have advice.
        Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
        if (specificInterceptors != DO_NOT_PROXY) {
            this.advisedBeans.put(cacheKey, Boolean.TRUE);
            // 创建代理,jdk动态代理或者cglib代理
            Object proxy = createProxy( bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
            this.proxyTypes.put(cacheKey, proxy.getClass());
            return proxy;
        }

    }

上述代码的作用就是,Spring在bean初始化之后,会判断该bean是否需要创建一个代理对象,如果需要,就会使用jdk动态代理或者cglib创建一个代理类(这一块不是本篇文章分析的重点)。

(四)、ProxyTransactionManagementConfiguration。

在这里插入图片描述
核心方法:transactionAdvisor()事务织入

定义了一个advisor,设置事务属性、设置事务拦截器TransactionInterceptor、设置顺序。核心就是事务拦截器TransactionInterceptor。

TransactionInterceptor使用通用的spring事务基础架构实现“声明式事务”,继承自TransactionAspectSupport类(该类包含与Spring的底层事务API的集成),实现了MethodInterceptor接口。spring类图如下:
在这里插入图片描述
事务拦截器的拦截功能就是依靠实现了MethodInterceptor接口,熟悉spring的同学肯定很熟悉MethodInterceptor了,这个是spring的方法拦截器,主要看invoke方法:

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

        // 调用TransactionAspectSupport的 invokeWithinTransaction方法
        return invokeWithinTransaction(invocation.getMethod(), targetClass, new InvocationCallback() {
            @Override
            public Object proceedWithInvocation() throws Throwable {
                return invocation.proceed();
            }
        });
    }

TransactionInterceptor复写MethodInterceptor接口的invoke方法,并在invoke方法中调用了父类TransactionAspectSupport的invokeWithinTransaction()方法,源码如下:

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;
            }
        }
    }

(五)、事务核心源码,获取事务信息,执行方法、提交或回滚。

在这里插入图片描述
如上提所示,PlatformTransactionManager顶级接口定义了最核心的事务管理方法,下面一层是AbstractPlatformTransactionManager抽象类,实现了PlatformTransactionManager接口的方法并定义了一些抽象方法,供子类拓展。最后下面一层是2个经典事务管理器:

1、DataSourceTransactionmanager

即JDBC单数据库事务管理器,基于Connection实现,

2、JtaTransactionManager

即多数据库事务管理器(又叫做分布式事务管理器),其实现了JTA规范,使用XA协议进行两阶段提交。

我们这里只看基于JDBC connection的DataSourceTransactionmanager源码。

PlatformTransactionManager接口:

public interface PlatformTransactionManager {
    // 获取事务状态
    TransactionStatus getTransaction(TransactionDefinition definition) throws TransactionException;
  // 事务提交
    void commit(TransactionStatus status) throws TransactionException;
  // 事务回滚
    void rollback(TransactionStatus status) throws TransactionException;
}
3、 getTransaction获取事务。

在这里插入图片描述
源代码如下:

@Override
    public final TransactionStatus getTransaction(TransactionDefinition definition) throws TransactionException {
        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());
        }
        // 当前不存在事务,传播机制=MANDATORY(支持当前事务,没事务报错),报错
        if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_MANDATORY) {
            throw new IllegalTransactionStateException(
                    "No existing transaction found for transaction marked with propagation 'mandatory'");
        }// 当前不存在事务,传播机制=REQUIRED/REQUIRED_NEW/NESTED,这三种情况,需要新开启事务,且加上事务同步
        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;
            }
        }
        else {
            // 当前不存在事务当前不存在事务,且传播机制=PROPAGATION_SUPPORTS/PROPAGATION_NOT_SUPPORTED/PROPAGATION_NEVER,这三种情况,创建“空”事务:没有实际事务,但可能是同步。
            //警告:定义了隔离级别,但并没有真实的事务初始化,隔离级别被忽略有隔离级别但是并没有定义实际的事务初始化,有隔离级别但是并没有定义实际的事务初始化,
            if (definition.getIsolationLevel() != TransactionDefinition.ISOLATION_DEFAULT && logger.isWarnEnabled()) {
                logger.warn("Custom isolation level specified but no actual transaction initiated; " +
                        "isolation level will effectively be ignored: " + definition);
            }
            boolean newSynchronization = (getTransactionSynchronization() == SYNCHRONIZATION_ALWAYS);
            return prepareTransactionStatus(definition, null, true, newSynchronization, debugEnabled, null);
        }
    }

源码分成了2条处理线,

(1).当前已存在事务:isExistingTransaction()判断是否存在事务,存在事务handleExistingTransaction()根据不同传播机制不同处理

(2).当前不存在事务: 不同传播机制不同处理handleExistingTransaction()。

4、commit提交事务

在这里插入图片描述

SqlSessionSynchronization是SqlSessionUtils的一个内部类,继承自TransactionSynchronizationAdapter抽象类,实现了事务同步接口TransactionSynchronization。TransactionSynchronization接口定义了事务操作时的对应资源的(JDBC事务那么就是SqlSessionSynchronization)管理方法:

// 挂起事务 
void suspend();
// 唤醒事务
void resume();

void flush();
// 提交事务前
void beforeCommit(boolean readOnly);
 // 提交事务完成前
void beforeCompletion();
// 提交事务后
void afterCommit();
// 提交事务完成后
void afterCompletion(int status);

**

5、 rollback回滚事务。

**
在这里插入图片描述
AbstractPlatformTransactionManager中rollback源码:

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);
    }

processRollback源码如下:

private void processRollback(DefaultTransactionStatus status) {
        try {
            try {// 解绑当前线程绑定的会话工厂,并关闭会话
                triggerBeforeCompletion(status);
                if (status.hasSavepoint()) {// 1.如果有保存点,即嵌套式事务
                    if (status.isDebug()) {
                        logger.debug("Rolling back transaction to savepoint");
                    }//回滚到保存点
                    status.rollbackToHeldSavepoint();
                }//2.如果就是一个简单事务
                else if (status.isNewTransaction()) {
                    if (status.isDebug()) {
                        logger.debug("Initiating transaction rollback");
                    }//回滚核心方法
                    doRollback(status);
                }//3.当前存在事务且没有保存点,即加入当前事务的
                else if (status.hasTransaction()) {//如果已经标记为回滚 或 当加入事务失败时全局回滚(默认true)
                    if (status.isLocalRollbackOnly() || isGlobalRollbackOnParticipationFailure()) {
                        if (status.isDebug()) {//debug时会打印:加入事务失败-标记已存在事务为回滚
                            logger.debug("Participating transaction failed - marking existing transaction as rollback-only");
                        }//设置当前connectionHolder:当加入一个已存在事务时回滚
                        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");
                }
            }
            catch (RuntimeException ex) {//关闭会话,重置SqlSessionHolder属性
                triggerAfterCompletion(status, TransactionSynchronization.STATUS_UNKNOWN);
                throw ex;
            }
            catch (Error err) {
                triggerAfterCompletion(status, TransactionSynchronization.STATUS_UNKNOWN);
                throw err;
            }
            triggerAfterCompletion(status, TransactionSynchronization.STATUS_ROLLED_BACK);
        }
        finally {、、解绑当前线程
            cleanupAfterCompletion(status);
        }
    }

三、总结。

申明式事务管理不需要入侵代码,是基于Aop,具体而言是通过一个TransactionInterceptor的拦截器来实现。通过@Transactional就可以进行事务操作,更快捷而且简单(尤其是配合spring boot自动配置,可以说是精简至极!),且大部分业务都可以满足,推荐使用。
**注意:**而在同一个class中,方法B调用方法A,调用的是原对象的方法,而不通过代理对象。所以Spring无法切到这次调用,也就无法通过注解保证事务性了。 也就是说,在同一个类中的方法调用,则不会被方法拦截器拦截到,因此事务不会起作用。

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值