关于循环依赖有的同学写的很好,贴出来:
https://www.cnblogs.com/tiger-fu/p/8961361.html
https://juejin.cn/post/6844903715602694152#heading-7
https://blog.csdn.net/LeoHan163/article/details/106343857
https://www.cnblogs.com/leeego-123/p/12165278.html
Spring中的循环依赖:
- 构造器循环依赖
是否解决:通过构造器注入构成的循环依赖,此依赖是无法解决的,只能抛出BeanCurrentlyInCreationException异常表示循环依赖。
原因:创建A类时,构造器需要B类,那将去创建B,在创建B类时又发现需要C类,则又去创建C,最终在创建C时发现又需要A,从而形成一个环,没办法创建。
实现有循环依赖时抛出异常:
Spring容器会将每一个正在创建的Bean 标识符放在一个“当前创建Bean池(singletonsCurrentlyInCreation)”中,Bean标识符在创建过程中将一直保持在这个池中。
因此如果在创建Bean过程中发现自己已经在“当前创建Bean池”里时将抛出BeanCurrentlyInCreationException异常表示循环依赖。
而对于创建完毕的Bean将从“当前创建Bean池”中清除掉。
- 属性注入循环依赖
prototype模式:有状态的bean都使用prototype作用域,无状态的一般都使用singleton单例作用域。
是否解决:"prototype"作用域bean,Spring容器无法完成依赖注入。
原因:“prototype”作用域的Bean,Spring容器不进行缓存,因此无法提前暴露一个创建中的Bean。
singleton模式
是否解决:是的
单例属性注入如何解决循环依赖
本质上,是通过将半成品实体(实例化,但还未进行属性注入的实体)存放到map中实现的。
用到的map
1.singletonObjects 单例对象列表, beanName -> bean实例。
2.singletonFactories 单例工厂列表 beanName -> beanFactory。
3.earlySingletonObjects 循环对象依赖列表,对象在创建之后,进行注入过程中,发现产生了循环依赖,那么会将对象放入到这个队列,并且从singletonFactories中移除掉。
4.singletonsCurrentlyInCreation 正在创建的单例名称队列。
5.registeredSingletons 已经创建成功的单例名称列表。
假设A与B相互依赖
实例化A之后,此时:
singletonFactories 包含 A
registeredSingletons 包含A
singletonsCurrentlyInCreation 包含A
singletonObjects 不包含A
earlySingletonObjects 不包含A
发现A需要注入B,于是实例化B,之后发现B需要A,于是map中拿到A,此时:
singletonFactories 不包含 A
registeredSingletons 包含A
singletonsCurrentlyInCreation 包含A
singletonObjects 不包含A
earlySingletonObjects 包含A
B获取了A,实例化、初始化完成,此时:
singletonFactories 不包含B
registeredSingletons 包含B
singletonsCurrentlyInCreation 不包含B
singletonObjects 包含B
earlySingletonObjects 不包含B
A继续初始化,由于上面B初始化完成,所以可以获得B,此时:
singletonFactories 不包含A
registeredSingletons 包含A
singletonsCurrentlyInCreation 不包含A
singletonObjects 包含A
earlySingletonObjects 包含A
主要使用了singletonFactories、earlySingletonObjects来解决循环依赖的问题。如果不是使用aop的情况下,使用一个map也可以解决循环依赖的问题。但是如果使用了aop,singletonFactories返回的代理对象每次都是不一样的,所需需要引入earlySingletonObjects。
网友评论