问题
现有代码如下:
public class TransactionService {
@Transactional(rollbackFor = Exception.class)
public void transactional() {
// DB operate
throw new RuntimeException();
}
public void notTransactional() {
// biz code
transactional();
// biz code
}
}
原因及解决思路
- 先获取Spring容器中
TransactionService
的 class name。 - 使用
arthas
attach 至当前JVM - arthas jad 反编译 class 至本地发现代理后的伪代码如下:
public class TransactionService$Proxy {
public final void notTransactional() {
// operation...
super.notTransactional();
return;
}
public final void transactional() {
// operation...
super.transactional();
return;
}
}
原来如此,Spring在为我们生成代理类时,并不是按照我们想的那样,只代理了需要切面的方法。没有标注 @Transactional 也会被代理类实现。那么这个问题就降级成了一个多态问题。
解决方式
public class TransactionService {
@Transactional(rollbackFor = Exception.class)
public void transactional() {
// DB operate
throw new RuntimeException();
}
@Transactional(rollbackFor = Exception.class)
public void notTransactional() {
// biz code
transactional();
// biz code
}
}
Note
事务的传播等级设置同样也会导致失效哦