spring循环依赖及三级缓存

概述

循环依赖就是依赖关系形成环,比如最简单的循环依赖:A对象依赖B,B对象依赖A

只有使用set方式注入且作用域为singleton的可以解决循环依赖问题,构造器注入和prototype的bean循环依赖都会报错。

三级缓存

spring内部是用三级缓存来解决循环依赖问题的。

缓存说明
singletonObjects 第一级缓存,存放可用的成品Bean
earlySingletonObjects 第二级缓存,存放半成品的Bean半成品的Bean是已创建对象,但是未注入属性和初始化。用以解决循环依赖。
singletonFactories 第三级缓存,存的是Bean工厂对象,用来生成半成品的Bean并放入到二级缓存中。用以解决循环依赖。

 

源码及流程分析

AbstractBeanFactory#doGetBean

注意doGetBean方法中有两个getSingleton,第一个依次从一二三级缓存中获取bean,没有则返回null,第二个从一级缓存中获取,没有调用createBean方法创建,然后放入一级缓存

首先获取beanA,调用getSingleton方法从缓存获取不到,调用createBean方法

AbstractAutowireCapableBeanFactory#doCreateBean

如果bean是单例的,允许循环依赖,并且正在创建中,就加入到三级缓存中,将beanA加入三级缓存

DefaultSingletonBeanRegistry#addSingletonFactory

 还是doCreateBean方法继续往下走,走到populateBean,给beanA填充属性,发现需要依赖beanB

调用getBean开始获取beanB,此时流程同上,缓存中没有,调用createBean方法创建B,将B加入三级缓存,调用populateBean又需要依赖A,此时调用getBean("beanA")走到getSingleton,依次从一二三级缓存中获取,最后将A放入二级缓存,从三级缓存删除

DefaultSingletonBeanRegistry#getSingleton

B创建完后,走到addSingleton方法,将B放入一级缓存并从其他两级缓存中删除,此时回到A的populate方法,A属性填充完后,也调用addSingleton方法,将A放入一级缓存。

 总结

可以看出,A的顺序是三级缓存->二级缓存->一级缓存,B的顺序是三级缓存->一级缓存

首先从缓存中获取A,获取不到然后创建,发现需要依赖B,将A放入三级缓存,这时的A是不完整的,

开始从缓存获取B,获取不到,创建B,又发现需要依赖A,将B放入三级缓存,从三级缓存中获取到早期的A,将A从三级缓存中删除,放入二级缓存,然后注入B中,此时B创建完成,将B从三级缓存移入一级缓存。

B实例化完成,继续创建A,创建完成,将A从二级缓存移入一级缓存。

posted @ 2020-12-09 20:06  gloomysun  阅读(606)  评论(0编辑  收藏  举报