Spring事务处理面试题

作者: AKyS佐毅 | 来源:发表于2018-08-22 22:06 被阅读86次

    1、Spring事务管理

    • Spring - 在同一个类中一个普通方法调用另一个有@Transcational注解的方法时,Spring事务管理还启作用吗?


    答案是不会起作用的。此处的this指向目标对象,因此调用this.b()将不会执行b事务切面,即不会执行事务增强,因此b方法的事务定义@Transactional(propagation = Propagation.REQUIRES_NEW)将不会实施.

    • 只要给目标类AServiceImpl的某个方法加上注解@Transactional,spring就会为目标类生成对应的代理类,以后调用AServiceImpl中的所有方法都会先走代理类(即使调用未加事务注解的方法a,也会走代理类),即在通过getBean("AServiceImpl")获得的业务类时,实际上得到的是一个代理类,假设这个类叫做AServiceImplProxy ,spring为AServiceImpl生成的代理类类似于如下代码:
     public class AServiceImplProxy implements AService{
    
          public void a() {
           //启动事务的代码
           //反射调用目标类的a方法
           //事务提交的代码
          }
        
          public void b() {
          //启动事务的代码
          //反射调用目标类的b方法
          //事务提交的代码
          }
    }
    
    • 使用AOP 代理后的方法调用执行流程:

    • 首先调用的是AOP代理对象而不是目标对象,首先执行事务切面,事务切面内部通过TransactionInterceptor环绕增强进行事务的增强,即进入目标方法之前开启事务,退出目标方法时提交/回滚事务。

    • Spring在处理@Tranasctional注解时,会“proxy”掉当前的类。

    • 如果A和B两个类都有@Transactional时,实际上运行的是A的代理类A‘, A,B的代理类B', B四个类的instance。

    • 一个外部服务调用A,实际上是 外部-->A'-->A-->B'-->B这样执行的。而抛出异常的代码实际上是在B‘做的。

    • 但是如果是同一个类内部方法直接调用的话,那么就是简单的方法直接调用,即 外部-->A'-->A方法1-->A方法2。 A方法1不会找到A'去调用。于是,“传播”的规则不会生效。

    • 这个问题的答案尽管简单,但是问题在于本来是希望注解可以完全隐藏掉内部的复杂性的,但是实际上往往出现“盖不住露馅“的情况。有的答友会强调“边界”啦,“概念“啦,这是Java这套体系为了维护一种模型,为了自洽,不得不搞出这样的抽象规则——这并不是什么好事。

    • 其实,如果用SQL直接写就是 “开始事务"--->“处理数据”--->“提交/回滚“这3步,简单直接。至少我暂时没看出来搞出很多@Transactional+传播属性有任何可以简化设计,提高代码可维护性上的好处。

    • 所以对于简单事务,不妨统一做一层Service,在入口加@Transactional,然后把数据源(或者等价的jdbcTemplate/mapper)往下层传。而下层就不需要考虑事务这件事了。

    2、推荐阅读

    相关文章

      网友评论

        本文标题:Spring事务处理面试题

        本文链接:https://www.haomeiwen.com/subject/liduiftx.html