【Spring类的自调用事务失效问题】(某个类中无事务方法调用有事务方法)

咱们先来看一个类

public class Demo{
@Transactional
public void insert() { /* … */ }

public void query() {
    this.insert();
}

}

可能会有不少人会跟我一样,觉得上面这种方式调用 query()方法时,insert()上的@Transactional注解还是会起作用的,insert()在被调用时,将会开启事务。 但是,当实际操作之后,你会发现,这样并不会开启新的事务?
为什么呢?
我们知道,Spring之所以可以对开启@Transactional的方法进行事务管理,是因为Spring为当前类生成了一个代理类,然后在运行相关方法时,会判断这个方法有没有@Transactional注解,如果有的话,则会开启一个事务。 但是,上面这种调用方式时,在调用query()时,使用的并不是代理对象,从而导致this.insert()时也不是代理对象,从而导致@Transactional失败。 其实现原理是 AOP , 而 AOP 的原理是动态代理 , 在自调用的过程中 , 是类自身的调用 ,而不是代理对象去调用, 那么就不会产生 AOP , 这样 Spring就不能把你的代码织入到约定的流程中 , 于是就产生了现在看到的失败场景。

换句话说,就是在spring得aop中,切面配置的是某个包下的某个方法,整个流程是加载Demo类,调用query()方法,再调用insert()方法,最终返回的是Demo类产生query()的结果,整个过程最终结果是没有事务管控的,所以说insert()方法事务失效!仅限于同一个类下,我觉得可以这样去理解。

那么,对于这种情况,要怎么处理呢?

首先,在spring的xml中加上如下配置

<aop:aspectj-autoproxy expose-proxy=“true”/>
1
然后,在baz() 中,改成如下方式调用

public class Demo{

@Timed
public void insert() { /* … */ }

public void query() {
    ((Demo) AopContext.currentProxy()).insert();
}

}

PS: 如果是通过 “@Aspect” 注解实现的 AOP,那么,暂时还没有找到方法来解决

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值