需求
一个 @Transactional 修饰的方法A 的内部要调用另一个用 @Async 修饰的方法B,并且方法B 要在方法A 的事务提交之后,异步执行,大致如下:
@Transactional
public void updateA(..) {
batchInsert(..);
update(..);
updateB(..);
}
@Async
public void updateB(..) {
update(..)
}
分析
- 方法A 和 方法B 假如在同一个类中
七墨博客 ,则方法B 的 @Async 注解会失效:
首先解释下 @Transactional 注解失效的原因:Sprin
因为 @Transactional 和 @Async 注解的实现都是基于 Spring 的 AOP ,而 AOP 的实现是基于动态代理实现的,故 @Async 失效的原理和 @Transactional 原理是一样的。(排除配置错误导致失效的原因)
常用的解决办法是将调用方法和被调用方法(@
- 如何保证方法A 的内部方法 batchInsert(..) 和 update(..) 事务提交之后再异步执行方法B?
通过以下代码实现:
TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronizationAdapter() {
3 @Override
4 public void afterCommit() {
5 // 事务提交完毕时,触发:方法B
6 updateB(..);
7 }
原理:提交一个事务同步处理,在事务 commit 之后执行,具体存放在 ThreadLocal(线程本地变量)中,事务 commit 后会去 ThreadLocal 里边取。源码 afterCommit 是空的,没有任何操作,可见是 Spring 专门预留给大家使用的。
解决
最终实现:
class A {
@Autowired
private B b;
@Transactional
public void updateA(..) {
batchInsert(..);
update(..);
TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronizationAdapter() {
@Override
public void afterCommit() {
b.updateB(..);
}
});
}
}
class B {
@Async
public void updateB(..) {
update(..)
}
}