Spring 事务、异步和循环依赖有什么关系?
2021-03-04 07:28
标签:article dea 前言 art loading 逻辑 添加 改变 instant 在循环依赖中有一种循环依赖,就是自注入:自己依赖自己。 在 Spring 自调用事务失效,你是怎么解决的? 有小伙伴提出可以自己注入自己来解决事务失效。 具体使用方式如下: 是不是发现很神奇的事情,事务生效了。 其实这里注入自己,其实是注入的一个代理对象,调事务,也是调的代理对象的事务,所以事务生效。 Spring 事务失效原因: 事务只能应用到 public 方法上才会有效; 发现 @Transactional 注解可以自注入解决事务失效的问题,在某次开发中,自然而然想到 @Async 异步是不是也可以自注入解决循环依赖的问题。 NO, NO, NO…… 事实告诉我们是不可以的! 从错误开始着手: 开始往上面反推 exposedObject == bean 是这一块出了问题。 也就是说异步的时候,再次从二级缓存中获取的和初始的不相同。 Object earlySingletonReference = getSingleton(beanName, false); 这一次获取的时候发现不同所以报错。 那就开始 Debug, 按照循环依赖的逻辑,执行到 执行 singleton.getObject 方法 而此时执行 getEarlyBeanReference 先判断 然后开始执行异步的 那就继续往下看 进入到 initializeBean 的逻辑,有一部分叫做 applyBeanPostProcessorsAfterInitialization 方面小伙伴搜索,所以贴出来代码关键字。IDEA 使用 循环执行后置处理器: 发现执行完 AsyncAnnotationBeanPostProcessor 这个 PostProcessor 后,对象被改变了。从而导致二级缓存和当前的 Bean 不同。 以上也就是为什么 @Async 自调用不可以,因为在后面初始化阶段被代理修改了对象。 先判断 InfrastructureAdvisorAutoProxyCreator true 生成一个代理对象。 事务的处理器 PersistenceExceptionTranslationPostProcessor 也没有执行。 继续 Debug 关注 applyBeanPostProcessorsAfterInitialization 执行结束,发现 Bean 没有发生改变。 可以看出图中有两处会执行 BeanPostProcessor : 也有其他的地方在执行后置处理器,比如 applyBeanPostProcessorsBeforeInitialization ,只不过这里关注这俩处。 而这两处都有可能生成代理对象, @Transactional 是在 getEarlyBeanReference 处生成的代理对象,所以后面判断 Bean 是否被改变时为 true,而 @Async 是在后面异步生成了代理对象,所以判断不通过。 至此,分析完毕,错误之处,欢迎指正。 Spring 事务、异步和循环依赖有什么关系? 标签:article dea 前言 art loading 逻辑 添加 改变 instant 原文地址:https://www.cnblogs.com/liuzhihang/p/spring-trans-async.html前言
事务的自注入
@Slf4j
@Service
public class OrderBizServiceImpl implements OrderBizService {
// 注入自己
@Autowired
private OrderBizService orderBizService;
@Override
public void callBack() throws Exception {
// 一系列的逻辑
// 需要事务操作更新订单和用户金额
orderBizService.updateOrderStatusAndUserBalance();
}
@Override
@Transactional(rollbackFor = Exception.class)
public void updateOrderStatusAndUserBalance() throws Exception {
// 内部是事务逻辑
}
}
事务需要从外部调用,Spring 自调用会失效;
建议事务注解 @Transactional 一般添加在实现类上。异步的自注入
populateBean
时,属性赋值,发现有依赖自己,此时会创建自己。InfrastructureAdvisorAutoProxyCreator
true 调用 wrapIfNecessary 判断是否生成一个代理对象,这里并没有生成代理对象。AsyncAnnotationBeanPostProcessor
判断为 false。所以没有执行异步的生成代理对象逻辑。
? + Shift + F
搜索。@Transactional 为什么可以呢?
总结
exposedObject == bean
为 false ,从而抛出异常。
相关推荐
上一篇:python定义函数和调用函数
下一篇:test_log-0 in dir D:\tmp\kafka-logs Caused by: java.nio.file.FileSystemExcept 错误问题
文章标题:Spring 事务、异步和循环依赖有什么关系?
文章链接:http://soscw.com/index.php/essay/59889.html