我的编程空间,编程开发者的网络收藏夹
学习永远不晚

Spring事务、异步和循环依赖的关系有哪些

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

Spring事务、异步和循环依赖的关系有哪些

这篇文章主要介绍“Spring事务、异步和循环依赖的关系有哪些”,在日常操作中,相信很多人在Spring事务、异步和循环依赖的关系有哪些问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”Spring事务、异步和循环依赖的关系有哪些”的疑惑有所帮助!接下来,请跟着小编一起来学习吧!

前言

在循环依赖中有一种循环依赖,就是自注入:自己依赖自己。

Spring事务、异步和循环依赖的关系有哪些

事务的自注入

在 Spring 自调用事务失效,你是怎么解决的? 有小伙伴提出可以自己注入自己来解决事务失效。

具体使用方式如下:

@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 事务失效原因:

事务只能应用到 public 方法上才会有效;事务需要从外部调用,Spring 自调用会失效;建议事务注解 @Transactional  一般添加在实现类上。

异步的自注入

发现 @Transactional 注解可以自注入解决事务失效的问题,在某次开发中,自然而然想到 @Async  异步是不是也可以自注入解决循环依赖的问题。

NO, NO, NO……

事实告诉我们是不可以的!

Spring事务、异步和循环依赖的关系有哪些

从错误开始着手:

Spring事务、异步和循环依赖的关系有哪些

抛出异常部分 doCreateBean

开始往上面反推 exposedObject == bean 是这一块出了问题。

也就是说异步的时候,再次从二级缓存中获取的和初始的不相同。

Object earlySingletonReference = getSingleton(beanName, false);

Spring事务、异步和循环依赖的关系有哪些

从二级缓存再次获取 Bean

这一次获取的时候发现不同所以报错。

那就开始 Debug, 按照循环依赖的逻辑,执行到 populateBean 时,属性赋值,发现有依赖自己,此时会创建自己。

执行 singleton.getObject 方法

Spring事务、异步和循环依赖的关系有哪些

getEarlyBeanReference

Spring事务、异步和循环依赖的关系有哪些

getBeanPostProcessors()

而此时执行 getEarlyBeanReference 先判断 InfrastructureAdvisorAutoProxyCreator true 调用  wrapIfNecessary 判断是否生成一个代理对象,这里并没有生成代理对象。

Spring事务、异步和循环依赖的关系有哪些

然后开始执行异步的 AsyncAnnotationBeanPostProcessor 判断为 false。所以没有执行异步的生成代理对象逻辑。

那就继续往下看

Spring事务、异步和循环依赖的关系有哪些

到这一步还是正常的

进入到 initializeBean 的逻辑,有一部分叫做 applyBeanPostProcessorsAfterInitialization

方面小伙伴搜索,所以贴出来代码关键字。IDEA 使用 ? + Shift + F 搜索。

Spring事务、异步和循环依赖的关系有哪些

applyBeanPostProcessorsAfterInitialization

循环执行后置处理器:

Spring事务、异步和循环依赖的关系有哪些

Spring事务、异步和循环依赖的关系有哪些

发现执行完 AsyncAnnotationBeanPostProcessor 这个 PostProcessor 后,对象被改变了。从而导致二级缓存和当前的  Bean 不同。

以上也就是为什么 @Async 自调用不可以,因为在后面初始化阶段被代理修改了对象。

@Transactional 为什么可以呢?

Spring事务、异步和循环依赖的关系有哪些

getEarlyBeanReference

Spring事务、异步和循环依赖的关系有哪些

getBeanPostProcessors()

先判断 InfrastructureAdvisorAutoProxyCreator true 生成一个代理对象。

Spring事务、异步和循环依赖的关系有哪些

生成代理对象

事务的处理器 PersistenceExceptionTranslationPostProcessor 也没有执行。

继续 Debug 关注 applyBeanPostProcessorsAfterInitialization

Spring事务、异步和循环依赖的关系有哪些

执行结束,发现 Bean 没有发生改变。

总结

  • @Transactional: 是在循环依赖从二级缓存升到三级缓存的时候已经生成了代理对象。

  • @Async: 是在初始化阶段(initializeBean)去生成代理对象。然后 @Async 导致后面判断 exposedObject == bean  为 false ,从而抛出异常。

Spring事务、异步和循环依赖的关系有哪些

自注入

可以看出图中有两处会执行 BeanPostProcessor :

  1. 在 singletonFactory.getObject 时,如果是 SmartInstantiationAwareBeanPostProcessor  的子类会执行 getEarlyBeanReference 方法。

  2. 在 initializeBean 的 applyBeanPostProcessorsAfterInitialization 时会执行所有  BeanPostProcessor 的 postProcessAfterInitialization 的方法。

也有其他的地方在执行后置处理器,比如 applyBeanPostProcessorsBeforeInitialization  ,只不过这里关注这俩处。

而这两处都有可能生成代理对象, @Transactional 是在 getEarlyBeanReference 处生成的代理对象,所以后面判断 Bean  是否被改变时为 true,而 @Async 是在后面异步生成了代理对象,所以判断不通过。

到此,关于“Spring事务、异步和循环依赖的关系有哪些”的学习就结束了,希望能够解决大家的疑惑。理论与实践的搭配能更好的帮助大家学习,快去试试吧!若想继续学习更多相关知识,请继续关注编程网网站,小编会继续努力为大家带来更多实用的文章!

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

Spring事务、异步和循环依赖的关系有哪些

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

Spring解决循环依赖的方式有哪些

小编给大家分享一下Spring解决循环依赖的方式有哪些,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!循环依赖就是N个类中循环嵌套引用,如果在日常开发中我们用new
2023-06-16

编程热搜

目录