lotus

贵有恒何必三更眠五更起 最无益只怕一日曝十日寒

  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

 

本博客分为两点,

一个是spring事务实现原理源码解读(个人能力,初步解读),

二是spring事务的传播属性

 

简单案例,保存订单,修改商品数量

就是这两个方法,第一个方法中引用了第二个方法,都用@Transactional注解。debug调用shopping方法。

 

spring事务实现的源码

在调用方法时会扫描@Transactional,进入方法前会判断是否有注解(在类上也会扫描到,具体扫描方式不是本博客重点)

接着debug这个test方法,会产生proxy的代理

进入proxy(动态代理)

也就是说通过AOP,在进入具体的方法之前,对方法进行了增强,具体增强什么,看下文。

在这个代理里面,实际做事情的是这个判断后的方法(前面都是一些判断),invocation的proceed()方法;

注:这里的invocation可以找到真正要调用的方法。

点进去看一下,重点是这个,invoke()方法,点进去

注;吐槽下,有的时候看源码就是一直点下去,但是不能忘了从哪里来,和最终目的,可以对着实际代码点进去看下,有点头大了。

继续点进去看下

好了,这个是重点,这个invokeWithTransaction方法做了很多事情,点进去看下

这个方法createTransactionIfNecessary()等会儿说(在spring的传播属性里面讲),看下面的try catch 

你点点点就会到反射到具体的方法,这个时候就会调用真正的方法,

所以这个方法已经被增强了,

有了异常会回滚,在catch里面,而且会throw出去(这里的抛出有讲究,上家公司就是这么处理事务的,要求自己对业务进行try catch手动编程)。

没有异常,就走下面的提交(具体的自己点进去看)

这就是大致的spring的事务实现,若有兴趣,可看下spring事务的传播属性

===========================================================================

spring事务的传播属性

好的,上面我说的createTransactionIfNecessary(),在这里说,

重点是这个接口里面的getTransaction()方法,很重要,跟进去,去实现里找到如下:

判断当前环境是否已经存在事务,有事务走里面方法,没有事务走外面继续走;

继续走,进行很多判断,这里就要说注解@Transactional的信息,重点关注propagation(传播行为)和isolation(隔离级别),会有默认值,不同的值会走不同的方法。

这里就是不同的传播行为会创建不同的事务,对!事务就是在这里创建的!

默认是required,会创建事务。如果不使用事务们就会有一个空的事务。

-----------

接下来讲测试代码的下一行,会进入调用代码更改数量,此方法也是有事务的,此时会走下图这里的标红框处,因为事务已经存在。

先上图

这里就是事务的传递了,上面做了总结,

使用当前事务没啥说的,就是用当前的事务,不创建新的。

重点说下required_new 和 nested(嵌套事务)

nested的话,走判断,如果可以创建savePoint,那就走嵌套事务,如果不可以,那就走required_new

1 required_new,挂起当前事务,创建新的事务,

required_new事务里面,回滚就回滚出去了,而且抛出去的错(如果此事务被自己catch掉,并且不抛出,那就另说),会被外层的事务catch到,所以就都回滚了。

2 nested 嵌套事务

nested事务里面,回滚的话,会回滚到保存点savePoint,不影响外层事务。而外部事务如果出错,会影响到嵌套事务,事务会回滚到保存点。(required_new事务结束就是提交了,nested 事务提交后的保存点还是有效的,所以会回滚到保存点)

posted on 2019-04-15 20:23  白露~  阅读(1028)  评论(0编辑  收藏  举报