Bean的循环依赖
- 循环依赖指的是依赖闭环的问题
- 解决
首先我们来实例化A,实例化A时并没有处理依赖注入,因此会得到半成品A。有了半成品A,它会被封装成一个ObjectFactory,并且把它放入第三个缓存区singletonFactories中。
接下来要处理A的依赖注入。需要注入B,则需要实例化B。实例化好B之后,在处理B的依赖注入之前会得到半成品B。半成品B,它也会被封装成一个ObjectFactory,并且把它放入第三个缓存区singletonFactories中。
接着处理B的依赖注入,它需要注入A。它先去singletonObjects中寻找,再去earlySingletonObjects中寻找,最后到singletonFactories中寻找。最终找到半成品A包装成的ObjectFactory,调用它的getObject方法得到半成品A,然后注入给B对象。此时就可以得到完整品B。最后把完整品B放入singletonObjects中(删除掉 singletonFactories中创建B的ObjectFactory),半成品A放入earlySingletonObjects中(singletonFactories中创建A的ObjectFactory也可以删除了)。
最后为A完成依赖注入,注入完整品B,得到完整品A。(删除掉earlySingletonObjects中的半成品A)
总结
问题:请聊一聊Bean的循环依赖
答案:
总:Bean的循环依赖指的是À依赖B,B又依赖A这样的依赖闭环问题,在Spring中,通过三个对象缓存区来解决循环依赖问题,这三个缓存区被定义到了DefaultSingletonBeanRegistry中,分别是singletonObjects用来存储创建完毕的Bean,earlySingletonObjecs用来存储未完成依赖注入的Bean,还有SingletonFactories用来存储创建Bean的ObjectFactory。假如说现在A依赖B,B依赖A,整个 Bean的创建过程是这样的
分:
- 首先,调用A的构造方法实例化A,当前的A还没有处理依赖注入,暂且把它称为半成品,此时会把半成品A封装到一个 ObjectFactory中,并存储到singletonFactories缓存区
- 接下来,要处理A的依赖注入了,由于此时还没有B,所以得先实例化一个B,同样的,半成品B也会被封装到ObjectFactory中并存储到singletonFactories缓存区
- 紧接着,要处理B的依赖注入了,此时会找到singletonFactories中A对应的ObjecFactory,调用它的getObject方法得到刚才实例化的半成品A (如果需要代理对象,则会自动创建代理对象,将来得到的就是代理对象) ,把得到的半成品A注入给B,并同时会把半成品A存入到earlySingletonObjects中,将来如果还有其他的类循环依赖了A,就可以直接从earlySingletonObjects中找到它了,那么此时 singletonFactories中创建A的ObjectFactory也可以删除了
- 至此,B的依赖注入处理完了后,B就创建完毕了,就可以把B的对象存入到singletonObjects中了,并同时删除掉 singletonFactories中创建B的ObjectFactory
- B创建完毕后,就可以继续处理A的依赖注入了,把B注入给A,此时A也创建完毕了,就可以把A的对象存储到 singletonObjects中,并同时删除掉earlySingletonObjects中的半成品A
- 截此为止,A和B对象全部创建完毕,并存储到了singletonObjects中,将来通过容器获取对象,都是从singletonObejcts中获取
总:总结起来还是一句话,借助于DefaultSingletonBeanRegistry的三个缓存区可以解决循环依赖问题