Spring声明式事务

  1. 首先spring声明式事务的实现是通过AOP来实现的。spring声明式事务有多种方式来声明,其中最常用的是使用Spring的tx命名空间和@transactional注解来实现。
  2. 在spring XML配置文件中,使用tx命名空间来配置spring事务,当然,aop一般也是要声明的,因为有一些声明式的事务配置元素是依赖于Spring的AOP配置元素;

  • 我们可以使用tx:advice来配置事务,但更多的时候我们通过注解来实现,即tx:annotation-driven;
  • tx:annotation-driven,默认会自动使用名称为transactionManager的事务管理器,所以,如果定义的事务管理器名称为transactionManager,那么就可以直接使用<tx:annotation-driven/>,不用手动设置manager="transactionManager" 属性;

3. spring同一个类中transactional注解无效分为两种情况:
  a. 外部方法调用A方法:这种情况下B的事务将不生效;

public class Test {

    public void A() {
        this.B();
    }

    @Transactional
    public void B() {
        System.out.println();
    }

}

  b. 外部方法调用A方法:这种情况下B的事务将不生效;

public class Test {

    @Transactional(propagation=Propagation.SUPPORTS)
    public void A() {
        this.B();
    }

    @Transactional(propagation=Propagation.REQUIRED)
    public void B() {
        System.out.println();
    }

}

  c. 原因是Spring的AOP是使用了一个代理对象来包装目标对象,并拦截目标对象的方法调用。这样的实现带来的影响是: 在目标对象中调用自己类内部实现的方法时,spring会为该方法所在的bean动态的生成一个代理类,当这个方法被调用时,实际上是代理类调用的,如果该方法有transactional注解,代理类在调用之前就会启动transactional,如果没有,代理类就不启动事务。然而,如果这个有注解的方法是被同一个类中的其他方法调用的,那么该方法的调用并没有通过代理类,而是直接通过原来的那个bean,所以就不会启动transaction,我们看到的现象就是@Transactional注解无效。

   d. 解决方法,可以把这两个方法放到两个类中进行调用;也可以使用 AspectJ 模式的事务实现:<tx:annotation-driven mode="aspectj"/>

原文地址:https://www.cnblogs.com/xiaozhang2014/p/7906088.html