[spring] 源码简析 如何解决循环依赖?
spring是创建实例的时候,是如何解决循环依赖的呢?
先来看一下isSingleton的实例getBean的整个流程:
步骤一
sharedInstance = getSingleton(name)
来获取缓存的单例实例
(来源两处,参见图中同色系框框,
一、单例创建完了会缓存一份singletonObjects;
二、创建过程中会缓存一份singletonFactories,创建完了删除)如果能够获取得到,则直接返回bean
如果获取不到,则走getSingleton来实例化单例(参见步骤二)
步骤二
getSingleton(name)
将自身加singletonsCurrentlyInCreation(正在创建的单例容器)中
执行createBean方法(步骤三)
将自身从singletonsCurrentlyInCreation(正在创建的单例容器)中移除
创建的单例实例加入到单例缓存singletonObjects中
步骤三
createBean方法
通过构造函数创建实例
如果是单例 & 允许循环依赖&
该bean在singletonsCurrentlyInCreation(正在创建的单例容器)中,则将上述创建的实例缓存到singletonFactories
populatBean依赖注入属性,如果属性是beanName,则调用getBean回到开头
假设spring没有去解决循环依赖的问题,假设新建如下两个类:
1@Component2public class A {34 @Autowired5 private B b;678 public A() {9 System.out.println("A Constructor"); 10 } 11 12 @Override 13 public String toString() { 14 return "A{}"; 15 } 16}1@Component2public class B {34 @Autowired5 private A a;678 public B() {9 System.out.println("B Constructor"); 10 } 11 12 13 @Override 14 public String toString() { 15 return "B{}"; 16 } 17}
那么,在创建A的单例的过程中,需要依赖注入B,转而去创建B,B的创建过程中又要依赖注入A,此时A在beanFactory中不存在,转而又去创建A,这样会形成一种死循环。
问题的解决办法,就是要在创建过程中,有一条分支路线能够终止创建过程并且返回对象。
spring是怎么解决循环依赖的呢?
在创建一个单例的过程中,一旦通过构造函数创建了一个实例,就将中间过程的实例对象暂时缓存起来。
--> 创建A①
--> 执行到步骤三的第2步时,会将刚刚通过构造函数新建的实例缓存起来
--> 执行步骤三的第3步,依赖注入B,去创建B
--> B又依赖注入A,创建A
--> 步骤一中能直接从缓存singletonFactories获取到对象 return a
--> invoke b.setA(a)
--> return B
--> invoke a.setB(b)
--> return A
以上
更多源码分析,关注公众号???
转载于:https://www.cnblogs.com/mianteno/p/10692633.html
[spring] 源码简析 如何解决循环依赖?相关推荐
- Spring 源码总结、IOC、循环依赖、AOP分析
Spring 源码 本文基于 jdk 11 核心类 interface BeanFactory 该接口是访问 Spring bean 容器的根接口,是 bean 容器的基本客户端视图: 其他接口如Li ...
- spring源码解析(五) 循环依赖
1.什么是循环依赖? Bean A → Bean B → Bean A 在A对象生命周期中注入B,进入B生命周期找A,但A还不存在,继续进入A对象生命周期找B,这就是循环依赖. 2.循环依赖造成的结果 ...
- spring源码阅读笔记09:循环依赖
前面的文章一直在研究Spring创建Bean的整个过程,创建一个bean是一个非常复杂的过程,而其中最难以理解的就是对循环依赖的处理,本文就来研究一下spring是如何处理循环依赖的. 1. 什么是循 ...
- Spring源码解析-三级缓存与循环依赖,nginx架构图
两个流程理论上是互不影响的 protected <T> T doGetBean(String name, @Nullable Class<T> requiredType, @N ...
- Spring-bean的循环依赖以及解决方式___Spring源码初探--Bean的初始化-循环依赖的解决
本文主要是分析Spring bean的循环依赖,以及Spring的解决方式. 通过这种解决方式,我们可以应用在我们实际开发项目中. 什么是循环依赖? 怎么检测循环依赖 Spring怎么解决循环依赖 S ...
- Spring Boot源码简析 @EnableTransactionManagement
相关阅读 Spring Boot源码简析 事务管理 Spring Boot源码简析 @EnableAspectJAutoProxy Spring Boot源码简析 @EnableAsync Sprin ...
- spring源码刨析总结
spring源码刨析笔记 1.概述 spring就是 spring Framework Ioc Inversion of Control(控制反转/反转控制) DI Dependancy Inject ...
- ffmpeg实战教程(十三)iJKPlayer源码简析
要使用封装优化ijk就必须先了解ffmpeg,然后看ijk对ffmpeg的C层封装! 这是我看ijk源码时候的笔记,比较散乱.不喜勿喷~ ijk源码简析: 1.ijkplayer_jni.c 封装的播 ...
- Log-Pilot 源码简析
Log-Pilot 源码简析 简单介绍 源码简析 Pilot结构体 Piloter接口 main函数 Pilot.Run Pilot.New Pilot.watch Pilot.processEven ...
- 【Golang源码分析】Go Web常用程序包gorilla/mux的使用与源码简析
目录[阅读时间:约10分钟] 一.概述 二.对比: gorilla/mux与net/http DefaultServeMux 三.简单使用 四.源码简析 1.NewRouter函数 2.HandleF ...
最新文章
- Camera+销量突破200万 创始人分享成功经验
- boost源码剖析之:Tuple Types(rev#2)
- UITableView 自带编辑删除 自己定义button
- idea apollo启动VM参数设置
- linux安装redis有什么用吗,Linux下 安装Redis
- Django(ORM常用字段)
- 单表查询 多表查询 子查询
- Windows系列服务器上配置JSP运行环境,以及网站上线
- 税务系统什么时候使用计算机,2020年税务师考试题量、答题要求及计算器使用规定...
- Arduino(c) 16进制转字符串
- Android 包大小优化总结
- 无向有权图的建立(邻接链表法) 广度优先搜索 深度优先搜素
- 全新来客码智能纳客营销系统免费使用功能效果
- Extracting and Composing Robust Features with Denoising Autoencoders论文笔记
- 51“motorrr”寻迹小车学习1电机和寻迹模块
- 尘埃粒子计数器帮助实时监测半导体车间空气中的粒子数
- Java数据结构告诉你如何选用数据集合(2)顺序表
- Windows远程桌面连接不上问题
- STM32 RTC LSE 初始化失败 卡在 RTC_ICSR_INITF 或者 LSERDY
- odoo小程序商城概览(睿鸥商城)
热门文章
- python全栈脱产第20天------常用模块---re模块和subprocess模块
- RobotFramework自动化测试框架-移动手机自动化测试Clear Text关键字的使用
- UVA10317- Equating Equations(回溯+剪枝)
- [转]刚成为程序员的你需要什么技能
- 危险无处不在 Html标签带来的安全隐患
- jmeter 压测之动态数据关联
- [luoguP3332] [ZJOI2013]K大数查询(树套树)
- zjufantasy.com开发日记(1)
- 原型与继承学习笔记3
- Android Studio单元测试入门