https://mp.weixin.qq.com/s/FtbzTMxHgzL0G1R2pSlh-A

通常来说,如果问Spring内部如何解决循环依赖,一定是单默认的单例Bean中,属性互相引用的场景。比如几个Bean之间的互相引用:

甚至自己“循环”依赖自己:

先说明前提:原型(Prototype)的场景是不支持循环依赖的,通常会走到AbstractBeanFactory类中下面的判断,抛出异常。

if (isPrototypeCurrentlyInCreation(beanName)) {
throw new BeanCurrentlyInCreationException(beanName);
}

原因很好理解,创建新的A时,发现要注入原型字段B,又创建新的B发现要注入原型字段A...

这就套娃了, 你猜是先StackOverflow还是OutOfMemory?Spring怕你不好猜,就先抛出了BeanCurrentlyInCreationException

基于构造器的循环依赖,就更不用说了,官方文档都摊牌了,你想让构造器注入支持循环依赖,是不存在的,不如把代码改了。那么默认单例的属性注入场景,Spring是如何支持循环依赖的?

Spring解决循环依赖

首先,Spring内部维护了三个Map,也就是我们通常说的三级缓存。笔者翻阅Spring文档倒是没有找到三级缓存的概念,可能也是本土为了方便理解的词汇。在Spring的DefaultSingletonBeanRegistry类中,你会赫然发现类上方挂着这三个Map:

  • singletonObjects 它是我们最熟悉的朋友,俗称“单例池”“容器”,缓存创建完成单例Bean的地方。
  • singletonFactories 映射创建Bean的原始工厂
  • earlySingletonObjects 映射Bean的早期引用,也就是说在这个Map里的Bean不是完整的,甚至还不能称之为“Bean”,只是一个Instance.

后两个Map其实是“垫脚石”级别的,只是创建Bean的时候,用来借助了一下,创建完成就清掉了。所以笔者前文对“三级缓存”这个词有些迷惑,可能是因为注释都是以Cache of开头吧。为什么成为后两个Map为垫脚石,假设最终放在singletonObjects的Bean是你想要的一杯“凉白开”。那么Spring准备了两个杯子,即singletonFactories和earlySingletonObjects来回“倒腾”几番,把热水晾成“凉白开”放到singletonObjects中。

最新文章

  1. uicode编码解码
  2. ip相关
  3. MySQL删除表数据
  4. python核心编程学习记录之数字
  5. ARM-Linux S5PV210 UART驱动(6)----platform device的添加
  6. 将PL/SQL代码封装在机灵的包中
  7. jQuery Vlidate 演示样例
  8. CentOS6.3下安装配置SVN(Subversion)
  9. RoleManager 进行角色管理
  10. 面向对象_04【关键字:super使用】
  11. java中面试可能会问的问题
  12. Vs2017 xaramin mac build agent部署后记
  13. js 实现二级联动
  14. django的FormView中,自定义初始化表单数据的曲折方法
  15. PowerShell使用ServicePrincipal登陆Azure
  16. python os详解
  17. P3157 [CQOI2011]动态逆序对(树状数组套线段树)
  18. actor binary tree lab4
  19. php判断正常访问和外部访问
  20. 一键安装openstack juno 之controller node.

热门文章

  1. IDEA SVN 使用
  2. 基于Hi3559AV100 RFCN实现细节解析-(2)RFCN数据流分析
  3. Vue 解决img标签不显示图片问题
  4. CCF(元素选择器:50分):字符串+模拟
  5. Mybatis系列全解(七):全息视角看Dao层两种实现方式之传统方式与代理方式
  6. 漏洞复现-Discuz-命令执行(wooyun-2010-080723)
  7. CVE-2019-2618 任意文件上传
  8. Windows-Redis占用C盘系统空间
  9. 《进击吧!Blazor!》系列入门教程 第一章 7.图表
  10. AmazonS3 使用AWS SDK for Java实现跨源资源共享 (CORS)