@Transactional注解真的有必要声明rollbackFor属性吗??今天在看spring的事务底层源码时,想到一个问题,@Transactional注解真的有必要声明rollbackFor属性吗?因为之前有许多资料,包括公司的java编码规范上也有提及到这一点 。
?不知道读者们有没想过这个问题,但我看完源码后,个人觉得是没必要的 。见解不到位的话,希望读者能指明 。
异常:如下图所示,我们都知道Exception分为运行时异常RuntimeException和非运行时异常(检查时异常) 。
文章插图
那么spring默认会对如上的哪些异常进行回滚呢?
答案:RuntimeException、Error.
spring源码如下说明:?spring在执行方法抛出异常后 , 会调用
completeTransactionAfterThrowing
方法,也在该方法中会去判断并执行是回滚还是提交操作 。protected void completeTransactionAfterThrowing(@Nullable TransactionInfo txInfo, Throwable ex) {if (txInfo != null && txInfo.getTransactionStatus() != null) {if (logger.isTraceEnabled()) {logger.trace("Completing transaction for [" + txInfo.getJoinpointIdentification() +"] after exception: " + ex);}// transactionAttribute的实现类为RuleBasedTransactionAttribute,父类为DefaultTransactionAttributeif (txInfo.transactionAttribute != null && txInfo.transactionAttribute.rollbackOn(ex)) {try {txInfo.getTransactionManager().rollback(txInfo.getTransactionStatus());}catch (TransactionSystemException ex2) {logger.error("Application exception overridden by rollback exception", ex);ex2.initApplicationException(ex);throw ex2;}catch (RuntimeException | Error ex2) {logger.error("Application exception overridden by rollback exception", ex);throw ex2;}}else {// We don't roll back on this exception.// Will still roll back if TransactionStatus.isRollbackOnly() is true.try {txInfo.getTransactionManager().commit(txInfo.getTransactionStatus());}catch (TransactionSystemException ex2) {logger.error("Application exception overridden by commit exception", ex);ex2.initApplicationException(ex);throw ex2;}catch (RuntimeException | Error ex2) {logger.error("Application exception overridden by commit exception", ex);throw ex2;}}}
我们看到这个if分支进行分析,如果该if满足,则会进行回滚 。if (txInfo.transactionAttribute != null && txInfo.transactionAttribute.rollbackOn(ex))
查看txInfo.transactionAttribute.rollbackOn(ex)方法,其中的this.rollbackRules
就是我们在@Transactional注解上配置的rollbackFor属性 , public boolean rollbackOn(Throwable ex) {RollbackRuleAttribute winner = null;int deepest = Integer.MAX_VALUE;if (this.rollbackRules != null) {// 遍历所有的RollbackRuleAttribute , 判断现在抛出的异常ex是否匹配RollbackRuleAttribute中指定的异常类型的子类或本身for (RollbackRuleAttribute rule : this.rollbackRules) {int depth = rule.getDepth(ex);if (depth >= 0 && depth < deepest) {deepest = depth;winner = rule;}}}// User superclass behavior (rollback on unchecked) if no rule matches.if (winner == null) {return super.rollbackOn(ex);}// ex所匹配的RollbackRuleAttribute,可能是NoRollbackRuleAttribute,如果是匹配的NoRollbackRuleAttribute,那就表示现在这个异常ex不用回滚return !(winner instanceof NoRollbackRuleAttribute);}
我这里简单配了个ServiceException 。如下图文章插图
根据一:在rollbackFor属性元素遍历时,会根据
getDepth
方法去找抛出的异常 , 是不是就是我们声明的rollbackFor属性中的异常,如果是,判断是不是NoRollbackRuleAttribute
类型,是的话就不回滚,否则就回滚 。再看
getDepth
方法,会根据抛出的异常 , 判断异常名字是否跟我们声明的异常是否相同,相同则返回,不同则递归抛出异常的父类,直到遍历到Throwable.class
顶类 。private int getDepth(Class<?> exceptionClass, int depth) {if (exceptionClass.getName().contains(this.exceptionName)) {// Found it!return depth;}// If we've gone as far as we can go and haven't found it...if (exceptionClass == Throwable.class) {return -1;}return getDepth(exceptionClass.getSuperclass(), depth + 1);}
根据二:如果getDepth
找不到对应的异常类,就从默认实现类DefaultTransactionAttribute.rollbackOn(Throwalbe x)
方法进行判断 。@Overridepublic boolean rollbackOn(Throwable ex) {return (ex instanceof RuntimeException || ex instanceof Error);}
DefaultTransactionAttribute
推荐阅读
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 笔仙怎么玩啊,玩了有后果吗,真的有笔仙吗
- 你手里的雅诗兰黛口红小样是真的还是假的
- 火山小视频是真的能赚钱吗(怎么利用抖音火山赚钱)
- 红米k40真的很差吗_红米k40最严重缺点
- 天选2真的很垃圾吗_天选2还值得买吗
- 千万别买爱敬气垫,真的难用!
- 新版人民币1000元-要出新版面值一千元的人民币?真的假的?
- 银镯子上有“足银999”是真的银镯子吗?标价是多少11511
- 堪称植物界中的吸甲醛之王,吊兰是否真的能吸收甲醛?
- 我看到我朋友买了一台打印机,可是我想问在家买打印机真的有必要吗?