千锋教育-做有情怀、有良心、有品质的职业教育机构

400-811-9990
手机站
千锋教育

千锋学习站 | 随时随地免费学

千锋教育

扫一扫进入千锋手机站

领取全套视频
千锋教育

关注千锋学习站小程序
随时随地免费学习课程

上海
  • 北京
  • 郑州
  • 武汉
  • 成都
  • 西安
  • 沈阳
  • 广州
  • 南京
  • 深圳
  • 大连
  • 青岛
  • 杭州
  • 重庆
当前位置:沈阳千锋IT培训  >  技术干货  >  Spring管理事务时可以捕获异常吗?

Spring管理事务时可以捕获异常吗?

来源:千锋教育
发布人:lx
时间: 2023-03-07 14:47:17

  Spring经典面试题

  题目再现

  最近又到了就业季,老师有很多学生也开始了求职面试,不过最近有好几个学生最近都碰到了一道相同的问题,他们纷纷跑来问老师这道题目该怎么回答。

  这是一道Spring的经典面试题,该题目可以说是一道用来检验程序员是否具有真实工作经验,是否做过项目开发的常见问题。

Spring管理事务

  先说答案

  这道题目是问,” Spring在进行事务管理时可以捕获异常吗? “

  老师先跟各位明确一下答案:不能捕获异常!

  那这是为什么呢?

  具体原因

  其实原因在于,Spring中的事务是声明式事务,也就是说Spring中的AOP事务是帮助管理其它数据库事务的,但其本身并没有提供事务,我们可以从Spring关于事务管理的源码来进行深入的了解。

  下面就是Spring关于事务的管理的源码:

  // Spring AOP执行事务的源码

  protected Object invokeWithinTransaction(Method method, @Nullable Class targetClass,

  final InvocationCallback invocation) throws Throwable {

  // If the transaction attribute is null, the method is non-transactional.

  TransactionAttributeSource tas = getTransactionAttributeSource();

  final TransactionAttribute txAttr = (tas != null ? tas.getTransactionAttribute(method, targetClass) : null);

  final TransactionManager tm = determineTransactionManager(txAttr);

  PlatformTransactionManager ptm = asPlatformTransactionManager(tm);

  final String joinpointIdentification = methodIdentification(method, targetClass, txAttr);

  if (txAttr == null || !(ptm instanceof CallbackPreferringPlatformTransactionManager)) {

  //1.根据当前是否存在事务,和不同的传播机制,去判断是要挂起事务,还是生成新的事务等

  TransactionInfo txInfo = createTransactionIfNecessary(ptm, txAttr, joinpointIdentification);

  Object retVal;

  try {

  // 2.执行目标方法

  retVal = invocation.proceedWithInvocation();

  }catch (Throwable ex) {

  // 3.在目标方法抛出异常时,判断是否需要进行回滚

  completeTransactionAfterThrowing(txInfo, ex);

  throw ex;

  } finally {

  // 4.清理事务信息,恢复挂起的事务

  cleanupTransactionInfo(txInfo);

  }

  if (vavrPresent && VavrDelegate.isVavrTry(retVal)) {

  // Set rollback-only in case of Vavr failure matching our rollback rules...

  TransactionStatus status = txInfo.getTransactionStatus();

  if (status != null && txAttr != null) {

  retVal = VavrDelegate.evaluateTryFailure(retVal, txAttr, status);

  }

  }

  commitTransactionAfterReturning(txInfo);

  return retVal;

  我们从SpringAOP事务的源代码中可以看出,如果当前业务中存在事务,底层代码会对整个业务逻辑的目标方法进行异常捕获操作,如果代码中出现问题将会通过catch代码块对事务进行回滚。

  所以如果此时在Spring的业务层中,对出现了异常的事务代码进行异常捕获操作,将会直接执行业务块中的catch代码,而不会执行Spring源代码中的catch代码块,所以事务就不会被回滚,仍会进行事务的提交操作。

  所以在实际业务代码中,我们一定要注意,如果加了事务注解,那一定不要在代码中进行捕获异常。如果你想让异常处理的更加规范,可以在捕获到异常之后,对异常记录或者处理之后,再抛出一个异常,这样才能被事务的拦截器捕获到进行回滚,否则事务就失去了其意义。

声明:本站稿件版权均属千锋教育所有,未经许可不得擅自转载。

猜你喜欢LIKE

为什么会出现ref?

2023-05-05

防抖和节流是什么?

2023-04-27

JS的原型与原型链是什么?

2023-04-20

最新文章NEW

什么是redux?

2023-05-05

vue的计算属性,特性,应用是什么?

2023-04-27

负载均衡原理是什么?

2023-04-25

相关推荐HOT

更多>>

快速通道 更多>>

最新开班信息 更多>>

网友热搜 更多>>