Spring相关04——Spring Bean相关02-循环依赖1

82 阅读2分钟

本文已参与「新人创作礼」活动,一起开启掘金创作之路。

循环依赖怎么产生?

简单来说,A依赖B,B依赖A

具体来说,spring中bean对象的创建都要经历实例化属性赋值初始化的过程

1.创建A对象时,实例化A对象,此时A对象中的b属性为空

2.从容器中查找B对象,如果找到了b就直接赋值,不存在循环依赖问题,找不到就要创建B对象

3.实例化B对象,此时B对象中的a属性为空,填充属性a

4.从容器中查找A对象,找不到a,需要创建a

Spring怎么解决循环依赖?

Spring内部通过三级缓存来解决循环依赖问题,三级缓存实际上是三个map结构的表,将不同状态的对象分开缓存,一级缓存由ConcurrentHashMap实现,存储初始化完成成品对象二级缓存由HashMap实现,存储属性赋值阶段半成品对象三级缓存由HashMap实现存储Bean的工厂

三级缓存:

一级缓存singletonObjectsConcurrentHashMap实现,也叫单例池,存放初始化完成成品对象.

二级缓存earlySingletonObjects,使用HashMap实现,存放处于属性赋值阶段半成品对象

三级缓存singletonFactories,使用HashMap实现,存放Bean的工厂value值是一个工厂

只有单例模式的Bean才能通过三级缓存来解决循环依赖的问题。

例如在A对象创建时:

  • 对象A创建的属性赋值阶段需要B对象的引用,于是先将A的工厂放入第三级缓存,去实例化B
  • B实例化的时候发现需要A对象,于是B先查一级缓存,没有A,再查二级缓存,还是没有A,就查三级缓存,找到A的工厂,从工厂获得A的引用,然后把引用存入二级缓存并删除三级缓存中的工厂。
  • B顺利初始化后,将自己放到一级缓存中(此时B里面的A依然是创建中的状态),然后回来继续创建A,从一级缓存中拿到B,并完成A的创建,然后把A移动到一级缓存中。