问题描述: 在service某方法中执行了a方法和b方法,a上面加了默认事务传播行为,b传播行为是REQUIRES_NEW,但是b失败导致了a事务的回滚,就很奇怪。
原因:jdk动态代理中执行嵌套方法不会走代理,而是把嵌套的方法直接移动到原方法进行执行了。
下面进行验证:
public class ObjectProxy implements InvocationHandler {
private Object target;
public ObjectProxy(Object target) {
this.target = target;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("==========6666===========");
return method.invoke(target,args);
}
public Object getProxy() {
return Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(),
target.getClass().getInterfaces(),this);
}
}
class Te{
public static void main(String[] args) {
SkuInfoServiceImpl skuInfoServiceImpl = new SkuInfoServiceImpl();
ObjectProxy objectProxy = new ObjectProxy(skuInfoServiceImpl);
SkuInfoService skuInfoService = (SkuInfoService) objectProxy.getProxy();
skuInfoService.test1();
// skuInfoService.test2();
}
}
public interface SkuInfoService extends IService<SkuInfoEntity> {
void test1();
void test2();
}
@Service("skuInfoService")
public class SkuInfoServiceImpl implements SkuInfoService {
@Override
public void test1() {
System.out.println("test1");
test2();
}
@Override
public void test2() {
System.out.println("test2");
}
比如执行上面代码,代理对象执行test1方法,test1中包含test2,test2方法并不会走代理对象。
执行结果,只会走一次代理。
==========6666===========
test1
test2
所以事务那边就说得通了,
解决办法:
强制使用Aop的cglib代理。启动类添加注解
@EnableAspectJAutoProxy(exposeProxy = true)
并且执行的时候,要分别从AopContext中获取当前代理对象xxxService,然后分别调用xxxService.a()和xxxService.b();
另外注意,b方法中的异常一定要在外面进行try catch,不然b方法的异常会一直往外抛导致所有事务均异常全部回滚,还误以为代理失败。