org.springframework.transaction.interceptor.TransactionAspectSupport#invokeWithinTransaction
前面我们聊事务开启的时候,说的是第 382 行代码。
然后 try 代码块里面执行的是我们的业务代码。
现在,我们要研究事务的提交了,所以主要看我框起来的地方。
首先 catch 代码块里面,392 行,看方法名称已经非常的见名知意了:
completeTransactionAfterThrowing 在抛出异常之后完成事务的提交。
你看我的代码,只是用到了 @Transactional 注解,并没有指定异常。
那么问题就来了:
Spring 管理的事务,默认回滚的异常是什么呢?
如果你不知道答案,就可以带着问题去看源码。
如果你知道答案,但是没有亲眼看到对应的代码,那么也可以去寻找源码。
如果你知道答案,也看过这部分源码,温故而知新。
先说答案:默认回滚的异常是 RuntimeException 或者 Error。
我只需要在业务代码里面抛出一个 RuntimeException 的子类,比如这样的:
然后在 392 行打上断点,开始调试就完事了:
只需要往下调试几步,你就能走到这个方法来:
org.springframework.transaction.interceptor.RuleBasedTransactionAttribute#rollbackOn
发现这个 winner 对象为空,接着走了这个逻辑:
return super.rollbackOn(ex);
答案就藏着这行代码的背后:
如果异常类型是 RuntimeException 或者 Error 的子类,那么就返回 true,即需要回滚,调用 rollback 方法:
如果返回为 false,则表示不需要回滚,调用 commit 方法:
那么怎么让它返回 false 呢?
很简单嘛,这样一搞就好了:
框架给你留了口子,你就把它用起来。
当我把代码改成上面那样,然后重新启动项目,再次访问代码。
我们去寻找出现指定异常不回滚的具体的实现逻辑在哪。
其实也在我们刚刚看到的方法里面:
你看,这个时候 winner 不为 null 了。它是一个 NoRollbackRuleAttribute 对象了。
所以就走入这行代码,返回 false 了: