开始用上一篇文章讲到的Spring依赖注入的步骤,用两个例子来推导一下整个过程,举例子有助于理解假相。

先用一个最简略的例子:没有依赖的单例bean的创立。

推导过程是须要上一篇文章的步骤的,要参照步骤一步一步来。

无依赖的单例Bean的创立

假如要创立单例bean A:

  1. 首先,getBean->deGetBean办法,调用getSingleton(beanName,true)办法。
  2. getSingleton(beanName,true)一次查看一级、二级、三级缓存,都没有A对象,返回null。
  3. 查看Dependon,假如没有设置,不须要创立DependOn对象。
  4. 调用getSingleton(beanName,factory)办法:查看一级缓存中不存在,将以后bean的name放入“正在创立中”列表,调用createBean创立bean。
  5. createBean创立A的实例,查看到以后bean在“正在创立中”列表中,则将以后bean放入三级缓存中。
  6. 调用populateBean进行属性填充,因为A对象没有依赖任何对象,所以不须要注入其余对象,间接实现属性填充。
  7. 调用返回到第4步getSingleton(beanName,factory)办法中,实现bean创立后,将以后bean name从“正在创立中”列表中移除。
  8. 将bean A从三级缓存、二级缓存中移除,放入一级缓存中。
  9. 实现bean A的创立。

循环依赖的单例Bean的创立过程

A依赖B,B依赖A,假如都是属性的相互依赖,即:

@Componentpublic class A {    @Autowired    private B b;}
@Componentpublic class B {    @Autowired    private A a;}

集体认为简单的循环依赖都能够转化为我依赖你、你依赖我这种模式,所以咱们还是试图把这个例子说的分明明确一点,关键步骤用图示的形式阐明。

假如首先创立A实例。

  1. 执行到getSingleton(beanName,boolean)办法的时候,三个缓存都空:
  2. 而后,接着执行到doCreateBean的时候,会把A的工厂办法放入到三级缓存,如图:
  3. 接下来就是populateBean办法,为bean A执行属性填充,查找到须要注入bean B,调用getBean,如图,用蓝色箭头示意,当执行到getSingleton(beanName,boolean)办法的时候,三个缓存中都没有bean B:
  4. 继续执行到doCreateBean的时候,会把B的工厂办法放入到三级缓存:
  5. 而后到populateBean办法,为bean B执行属性填充,查找到须要注入bean A。
  6. 调用getBean(A),如图,用红色箭头示意,当执行到getSingleton(beanName,boolean)办法的时候,三级缓存中存在bean A,所以,利用工厂办法创立A对象,放入二级缓存,返回bean A,并将A从三级缓存移除:
  7. 返回到步骤5,将bean A赋值给bean B的属性a,实现bean B的属性填充。之后返回到第4步,实现bean B的doCreateBean办法,将Bean B放入一级缓存,同时将Bean B从二级、三级缓存移除:

这一步实现之后,Bean B实现了创立,也实现了他的属性A的依赖注入,然而注入的Bean A是个半成品,还放在二级缓存中,尚未实现创立。

然而因为Bean A的创立流程还没有完结,所以不会有问题,接下来的步骤会实现Bean A的创立。

  1. 流程返回到第3部,bean A的populateBean办法获取到了曾经实现创立的bean B对象,实现Bean A的属性注入。
  2. 之后继续执行bean A的doCreateBean的后续逻辑,实现Bean A的创立,将Bean A放入到一级缓存,并从二级、三级缓存移除:
  3. 实现bean A和bean B的创立,实现A、B之间的依赖注入。

小结

用图解的形式阐明Spring通过三级缓存解决依赖注入的过程。其实集体了解,对于更加简单的依赖关系,注入过程无非就是在以上10个步骤之间一直递归调用的过程。

据说有一个问题是,Spring三级缓存的必要性,前面的文章会尝试答复这个问题。

上一篇 Spring FrameWork从入门到NB -三级缓存解决循环依赖底细 (一)