(最详细的)深入理解 Spring 之 SpringBoot 事务原理(值得收藏)

前言在我们日常使用这些框架的时候,还有哪些疑问呢?就楼主而言,楼主已经明白了 IOC ,AOP 的原理,也明白了 Mybatis 的原理,也明白了 Spring 和 Mybatis 是如何整合的。但是,我们漏掉了 JavaEE 中一个非常重要的特性:事务。事务是 Java 程序员开发程序时不可避免的问题。我们就不讨论 ACID 的事务特性,楼主这里假定大家都已经了了解了事务的原理。那么,我们今天的任务是剖析源码,看看Spring 是怎么运行事务的,并且是基于当前最流行的SpringBoot。还有,我们之
摘要由CSDN通过智能技术生成

前言

在我们日常使用这些框架的时候,还有哪些疑问呢?就楼主而言,楼主已经明白了 IOC ,AOP 的原理,也明白了 Mybatis 的原理,也明白了 Spring 和 Mybatis 是如何整合的。但是,我们漏掉了 JavaEE 中一个非常重要的特性:事务。事务是 Java 程序员开发程序时不可避免的问题。我们就不讨论 ACID 的事务特性,楼主这里假定大家都已经了了解了事务的原理。那么,我们今天的任务是剖析源码,看看Spring 是怎么运行事务的,并且是基于当前最流行的SpringBoot。还有,我们之前剖析Mybatis 的时候,也知道,Mybatis 也有事务,那么,他俩融合之后,事务是交给谁的?又是怎么切换的?今天这几个问题,我们都要从源码中找到答案。

1. Spring 的事务如何运行?

如果各位使用过SpringBoot ,那么就一定知道如何在Spring中使用注解,比如在一个类或者一个方法上使用 @Transactional 注解,在一个配置类上加入一个 @
EnableTransactionManagement 注解代表启动事务。而这个配置类需要实现 TransactionManagementConfigurer 事务管理器配置接口。并实现 annotationDrivenTransactionManager 方法返回一个包含了 配置好数据源的 DataSourceTransactionManager 事务对象。这样就完成了事务配置,就可以在Spring使用事务的回滚或者提交功能了。

这个 saveList 方法就在Spring事务的控制之下,如果发生了异常,就会回滚事务。如果各位知道更多的Spring的事务特性,可以在注解中配置,比如什么异常才能回滚,比如超时时间,比如隔离级别,比如事务的传播。就更有利于理解今天的文章了。

我们基于一个 Junit 测试用例,来看看Spring的事务时如何运行的。

在测试用例中执行该方法,参数时一个空的List,这个Sql的运行肯定是失败的。我们主要看看他的运行过程。我们讲断点打在该方法上。断点进入该方法。

注意,
dataCollectionShareService 对象已经被 Cglib 代理了,那么他肯定会走 DynamicAdvisedInterceptor 的 intercept 方法,我们断点进入该方法查看,这个方法我们已经很属性了,该方法中,最重要的事情就是执行通知器或者拦截器的方法,那么,该代理有通知器吗?

有一个通知器。是什么呢?

一个事务拦截器,也就是说,如果通知器链不为空,就会依次执行通知器链的方法。那么 TransactionInterceptor 到底是什么呢?

该类实现了通知器接口,也实现类 MethodInterceptor 接口,并实现了该接口的 invoke 方法,在 DynamicAdvisedInterceptor 的 intercept 方法中,最终会调用每个 MethodInterceptor 的 invoke 方法,那么,TransactionInterceptor 的 invoke 方法是如何实现的呢?

invoke 方法中会调用自身的 invokeWithinTransaction 方法,看名字,该方法和事务相关。该方法参数是由目标方法,目标类,一个回调对象构成。 那么我们就进入该方法查看,该方法很长:

    /**
     * General delegate for around-advice-based subclasses, delegating to several other template
     * methods on this class. Able to handle {@link CallbackPreferringPlatformTransactionManager}
     * as well as regular {@link PlatformTransactionManager} implementations.
     * @param method the Method being invoked
     * @param targetClass the target class that we're invoking the method on
     * @param invocation the callback to use for proceeding with the target invocation
     * @return the return value of the method, if any
     * @throws Throwable propagated from the target invocation
     */
    protected Object invokeWithinTransaction(Method method, Class<?> targetClass, final InvocationCallback invocation)
            throws Throwable {

        // If the transaction attribute is null, the method is non-transactional.
        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, tx
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值