您的位置:首页 > 编程语言 > Java开发

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

2019-04-18 14:32 1971 查看

咱们先来看一个类

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,那么,暂时还没有找到方法来解决

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐