Spring 事务传播行为

 

Spring事务传播属性

Spring 事务传播属性,描述了Spring 的各个事务方法在相互调用时,事务是如何进行传播的。

Spring 事务有七个传播属性

C2fDbK04kD

Spring 事务控制原理

Spring 的事务控制是通过 Spring AOP 实现的,事务的 commit 或 rollback 操作都在 Spring 创建的代理类中实现。

举例说明,ServiceA.method1() 方法配置了 Spring 事务,实际 Spring 通过 AOP 生成了类 $ProxyA ,通过调用 $ProxyA 中增强的 method1() 方法(加入事务控制)来实现业务功能 & 事务控制。

Spring 事务传播的误区

有的同学可能会遇到一个问题,method1() 中调用 method2(),明明调用的 method2() 已经配置事务传播属性为 required_new,可是 Spring 并未给 method2() 开启新的事务。

查看代码发现,原来 method1() 和 method2() 在同一个类 ServiceA 中。

通过 Spring 事务控制原理可知,Spring 会生成代理类 $ServiceA,并通过调用 $ServiceA.method1() 来实现业务功能及事务控制;此时在 $ServiceA.method1() 中调用 method2(),实际上是不会生成新的代理类来增强 method2() 的,所以这时候 Spring 不会给 method2() 开启新的事务。

因此可知,同一个类中的方法相互调用,事务传播行为由最外层的方法的事务传播属性决定

要解决这个问题,我目前知道有如下3种方法:

  • 新建类 ServiceB,将 method2() 迁移到新的类中;

  • 在 ServiceA.method1() 中,重新通过 Spring IOC 获取 ServiceA

    ServiceA serviceA2 = applicationContext.getBean("serviceA");
    

    再通过新获取的 serviceA2 来调用 method2()。此方法不推荐。

  • 通过Spring配置暴露代理

    • <aop:aspectj-autoproxy expose-proxy="true"/>
      

    • <aop:config expose-proxy="true"/>
      

      总而言之,尽量通过合理的建模或设计来利用Spring AOP带来的方便,并避免随之带来的问题。