Spring 事务嵌套的问题

Aop的局限性导致嵌套事务的问题

事情是这样的:

​ 事务都是XML声明拦截 service 包路径下的所有事务

​ 由于这次项目 在service上面直接就是Controller

​ 不想在 Controller 中编写逻辑代码

​ 就想 声明式事务 和 注解事务 同时使用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public class DemoServiceImpl implements IDemoService {

//xml中声明了 拦截Service包下的所有方法
public void demo(String msg) {
for(xxx in xxx){
try{
this.work(msg); // *** 代码 1 ***
}catch(Exception e){
//不回滚
}
}
}

@Transactional(propagation = Propagation.REQUIRES_NEW)
public void work(String msg) {
//这里的逻辑出错的话需要单独回滚
//不回滚for调用的前一个方法的提交
}
}

按逻辑应该是没问题的

但是调用之后 并不触发work方法的回滚

原因是:

​ Spring Aop 代理的是 IDemoService 这个对象 并不是代理方法 通过 IDemoService 注入的Bean

​ 比如

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
@Autowired
IDemoService demoService;


demoService.demo();
//这样调用 demo是有被切入的
//这个 demoService 是Spring生成的动态对象 x

x 有个 dome方法
x.dome 去调用 DemoServiceImpl.dome
所以 x.dome有被注入事务管理 有被aop切入
this.work是 原始方法没有过代理对象所以没有被切入

// x 的方法有被代理
//而 this.work(msg); 这样调用的 就是DemoServiceImpl 中的work方法 并没有经过代理对象 x
//所以并不会进入Aop
//因此 @Transactional 注解也就不生效了

解决方式:

1.   AopContext.currentProxy()  获取当前的代理对象 通过代理对象调用 work方法
 2.   work 写到其他 Service 通过其他Service 调用

原本以为是 Spring 不能同时使用两种代理方式的问题

找了半天 修改了半天配置 结果是AOP代理的局限性导致的问题 捂脸>_<!!!

1
2
3
//原来以为是 
TransactionInterceptor interceptor = (TransactionInterceptor) event.getApplicationContext().getBean(TransactionInterceptor.class);
interceptor.setTransactionAttributeSources(new AnnotationTransactionAttributeSource(),interceptor.getTransactionAttributeSource());

实际上

​ @ImportResource 的XML中 有填写 tx:annotation-driven 就可以同时使用 两种事务管理方式