Spring解决循环依赖是有前置条件的:

  1. 呈现循环依赖的Bean必须要是单例
  2. 依赖注入的形式不能全是结构器注入的形式
依赖状况依赖注入形式循环依赖是否被解决
AB相互依赖(循环依赖)均采纳setter办法注入
AB相互依赖(循环依赖)均采纳结构器注入
AB相互依赖(循环依赖)A中注入B的形式为setter办法,B中注入A的形式为结构器
AB相互依赖(循环依赖)B中注入A的形式为setter办法,A中注入B的形式为结构器

创立A的过程实际上就是调用getBean办法,这个办法有两层含意

  1. 创立一个新的Bean
  2. 缓存中获取到曾经被创立的对象

????

Spring通过三级缓存解决了循环依赖,其中一级缓存为单例池singletonObjects),二级缓存为晚期曝光对象earlySingletonObjects),三级缓存为晚期曝光对象工厂singletonFactories)。

getSingleton(beanName, true)这个办法实际上就是到缓存中尝试去获取Bean,整个缓存分为三级

  1. singletonObjects,一级缓存,存储的是所有曾经齐全创立好了的单例Bean
  2. earlySingletonObjects,实现实例化,然而还未进行属性注入及初始化的对象
  3. singletonFactories,提前裸露的一个单例工厂,二级缓存中存储的就是从这个工厂中获取到的对象

当A、B两个类产生循环援用时,在A实现实例化后,就应用实例化后的对象去创立一个对象工厂并增加到三级缓存中,如果A被AOP代理,那么通过这个工厂获取到的就是A代理后的对象,如果A没有被AOP代理,那么这个工厂获取到的就是A实例化的对象。

当A进行属性注入时,会去创立B,同时B又依赖了A,所以创立B的同时又会去调用getBean(a)来获取须要的依赖,此时的getBean(a)会从缓存中获取:
第一步,先获取到三级缓存中的工厂;
第二步,调用对象工工厂的getObject办法来获取到对应的对象,失去这个对象后将其注入到B中。紧接着B会走完它的生命周期流程,包含初始化、后置处理器等。

当B创立完后,会将B再注入到A中,此时A再实现它的整个生命周期。至此,循环依赖完结!

面试官:”为什么要应用三级缓存呢?二级缓存能解决循环依赖吗?“
答:如果要应用二级缓存解决循环依赖,意味着所有Bean在实例化后就要实现AOP代理,这样违反了Spring设计的准则,Spring在设计之初就是通过AnnotationAwareAspectJAutoProxyCreator这个后置处理器来在Bean生命周期的最初一步来实现AOP代理,而不是在实例化后就立马进行AOP代理。

转载:讲一讲Spring中的循环依赖