在讨论Spring中事务失效问题前请参考Spring代理文章
1,首先明确一点
在开启事务后,从Spring中获取的对象是代理对象ProxyFactory并不是UserService对象
public class ProxyFactory{
private UserService target;
public ProxyFactory(Object target){
this.target=target;
}
//给目标对象生成代理对象
public Object getProxyInstance(){
return Proxy.newProxyInstance(
target.getClass().getClassLoader(),
target.getClass().getInterfaces(),
(proxy, method, args) -> {
System.out.println("代理方法执行前.....");
//执行目标对象方法
Object returnValue = method.invoke(target, args);
System.out.println("代理方法执行后.....");
return returnValue;
}
);
}
}
————————————————
版权声明:本文为CSDN博主「老马回头不吃草」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/u014533485/article/details/107529445
2,假设我们现在执行方法
@Trancational
public void a(){
// sql插入
xxxxxx
b();
}
@Trancational
public void b(){
// sql插入
xxxxx
//抛出异常
throw .....
}
此时B方法的事务是不会生效的!!
因为此时调用b()的方法是target对象 而不是代理对象
只有代理对象才会执行事务代码,走事务
然而此时执行的代码如下:
public class ProxyFactory{
private UserService target;
public ProxyFactory(Object target){
this.target=target;
}
//给目标对象生成代理对象
public Object getProxyInstance(){
return Proxy.newProxyInstance(
target.getClass().getClassLoader(),
target.getClass().getInterfaces(),
(proxy, method, args) -> {
System.out.println("代理方法执行前.....");
// 开启事务
transactionManager.
getTransaction(transactionDefinition);
//执行目标对象方法
Object returnValue = method.invoke(target, args);
//** 此时的method = A(){B()}
//** 统一走在了同一个事务里面
// 提交事务
transactionManager.commit(status);
System.out.println("代理方法执行后.....");
return returnValue;
}
);
}
}
如何解决?
1,从Spring容器中获取代理对象
2,将方法拆分到不用的对象中