码农日记

薄洪涛的个人博客

spring循环依赖

什么是循环依赖?

很简单,就是A对象依赖了B对象,B对象依赖了A对象

在Spring中,⼀个对象并不是简单new出来了,⽽是会经过⼀系列的Bean的⽣命周期,就是因为 Bean的⽣命周期所以才会出现循环依赖问题。当然,在Spring中,出现循环依赖的场景很多,有的场景 Spring⾃动帮我们解决了,⽽有的场景则需要程序员来解决

Bean的⽣命周期指的就是:在Spring中,Bean是如何⽣成的?
被Spring管理的对象叫做Bean。

Bean的⽣成步骤
  1. Spring扫描class得到BeanDefinition

  2. 根据得到的BeanDefinition去⽣成bean

  3. ⾸先根据class推断构造⽅法

  4. 根据推断出来的构造⽅法,反射,得到⼀个对象(暂时叫做原始对象)

  5. 填充原始对象中的属性(依赖注⼊)

  6. 如果原始对象中的某个⽅法被AOP了,那么则需要根据原始对象⽣成⼀个代理对象

  7. 把最终⽣成的代理对象放⼊单例池(源码中叫做singletonObjects)中,下次getBean时就直接从单例
    池拿即可

产生场景

ABean创建-->依赖了B属性-->触发BBean创建--->B依赖了A属性--->需要ABean(但ABean还在创建过程中)

从⽽导致ABean创建不出来,BBean也创建不出来。 这是循环依赖的场景

image.png


三级缓存

在Spring中,通过某些机制帮开发者解决了部分循环依赖的问题, 这个机制就是三级缓存,三级缓存是通⽤的叫法。

⼀级缓存为:singletonObjects

⼆级缓存为:earlySingletonObjects

三级缓存为:singletonFactories

image.png

A的Bean在创建过程中,在进⾏依赖注⼊之前,先把A的原始Bean放⼊缓存(提早暴露,只要放到缓存了,其他Bean需要时就可以从缓存中拿了),放⼊缓存后,再进⾏依赖注⼊,此时A的Bean依赖了B的Bean,如果B的Bean不存在,则需要创建B的Bean,⽽创建B的Bean的过程和A⼀样,也是先创建⼀个B的原始对象,然后把B的原始对象提早暴露出来放⼊缓存中,然后在对B的原始对象进⾏依赖注⼊A,此时能从缓存中拿到A的原始对象(虽然是A的原始对象,还不是最终的Bean),B的原始对象依赖注⼊完了之后,B的⽣命周期结束,那么A的⽣命周期也能结束。

因为整个过程中,都只有⼀个A原始对象,所以对于B⽽⾔,就算在属性注⼊时,注⼊的是A原始对象,也没有关系,因为A原始对象在后续的⽣命周期中在堆中没有发⽣变化。

注意:


  • 评论列表

发表评论:

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

Powered By Z-BlogPHP 1.7.3

版权所有 | 转载请标明出处