spring 提供了强大的事物管理机制,直接到在方法或者类上加@Transactional,也可以使用XML配置事物。
在一次的测试中发现当一个方法在同一个类被其它方法调用的时候,导致事物的传播行为不生效。
具体说明:
类结构:
public class Demo {
public void methodA() {
this.methodB();
}
public void methodB() {
}
}
1、如果在methodA中加入:@Transactional,mehodB不加@Transactional,那么调用methodA,methodA的事物会生效,因为methodA默认的propagation为PROPAGATION_REQUIRED,此时methodB会加入到methodA中
2、如果methodA与methodB都加上@Transactional,那么调用methodA,methodA的事物会生效,此时和 1 中情况一样,事物会生效,也是由于methodB的事物会加入到methodA中,但是,其实methodA中通过this.methodB()的调用是没有触发spring 的事物,原因会统一讲解。
3、如果methodA配置@Transactional,methodB配置@Transactional( propagation = Propagation.REQUIRES_NEW ),那么调用methodA,如果methodA出现异常,根据spring的事物传播行为,其实methodB应该是入库才对,但是我测试发现根本没有生效,一样是全部回滚。
原因解释:
spring的事物管理通过AOP代理来实现, 根据aop的思想,不可能在具体类Demo上直接处理事物,而是通过代理类来处理,代理类在调用具体类的方法来实现,根据上面的情景methodA通过this调用methodB,那么此时相当于调用methodB时是没有经过代理类的调用,因此spring无法对事物的传播行为做处理。
下面CGLIB生成的代理对象反编译的类文件:
其实JDK代理,也是类似的原理,不同的是,JDK代理是通过实现接口来重新生成代理对象,通过反射调用被代理类的方法