一句话总结:使用Spring等容器管理事务,当存在跨方法、跨类的调用时,Spring等容器通过事务传播机制维护事务的统一或事务的调用链。

 

当我们使用Spring配置文件或注解配置事务时,我们知道Spring通过动态代理技术自动在方法前后注入了事务处理代码,如下:

methodA() {
  Connection con = null; 
  try{ 
        con = getConnection(); 

        // your business code 

        con.commit(); 
  } catch(RuntimeException ex) { 
        con.rollback(); 
  } finally {    
        closeCon(); 
  }   
}

 

那么,如果方法A调用了方法B这种场景Spring会怎样处理呢,按上面所说Spring会自动给方法A和方法B都自动注入事务处理代码,那么方法A和方法B就是两个事务,那若在方法A中出现异常,方法A回滚了,方法B会回滚么?

methodA(){
  methodB();
}

 

为了解决这个问题,要么方法A和方法B是同一个事务,要么Spring需要维护事务的调用链,来控制A事务回滚关联回滚B事务,这就是事务传播机制。具体要使用同一事务还是多个事务调用链可根据业务配置,如下表格,但绝大多数情况采用Required配置维持同一个事务。

传播行为 含义
PROPAGATION_REQUIRED 表示当前方法必须运行在事务中。如果当前事务存在,方法将会在该事务中运行。否则,会启动一个新的事务
PROPAGATION_SUPPORTS 表示当前方法不需要事务上下文,但是如果存在当前事务的话,那么该方法会在这个事务中运行
PROPAGATION_MANDATORY 表示该方法必须在事务中运行,如果当前事务不存在,则会抛出一个异常
PROPAGATION_REQUIRED_NEW 表示当前方法必须运行在它自己的事务中。一个新的事务将被启动。如果存在当前事务,在该方法执行期间,当前事务会被挂起。如果使用JTATransactionManager的话,则需要访问TransactionManager
PROPAGATION_NOT_SUPPORTED 表示该方法不应该运行在事务中。如果存在当前事务,在该方法运行期间,当前事务将被挂起。如果使用JTATransactionManager的话,则需要访问TransactionManager
PROPAGATION_NEVER 表示当前方法不应该运行在事务上下文中。如果当前正有一个事务在运行,则会抛出异常
PROPAGATION_NESTED 表示如果当前已经存在一个事务,那么该方法将会在嵌套事务中运行。嵌套的事务可以独立于当前事务进行单独地提交或回滚。如果当前事务不存在,那么其行为与PROPAGATION_REQUIRED一样。注意各厂商对这种传播行为的支持是有所差异的。可以参考资源管理器的文档来确认它们是否支持嵌套事务

 

至于Spring事务传播机制是怎样实现的,作者也没进行深入研究,猜测是将事务对象存储在ThreadLocal中,若配置为Required传播即同一个事务,那么每个方法都返回该事务对象。若配置为多事务传播,那么事务对象要设计成类似LinkArrayList这样的链式数据结构,当回滚时可顺序地、链条式地回滚多个事务。上诉只是作者猜测哈,有兴趣同学可参考引用链接深入研究。

 

引用:

https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/transaction/annotation/Propagation.html

https://www.ibm.com/developerworks/cn/java/j-master-spring-transactional-use/index.html

https://blog.csdn.net/yaoqinggg/article/details/51772112

 

版权声明:本文为yuzhengzhong原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://www.cnblogs.com/yuzhengzhong/p/9771521.html