开始用上一篇文章讲到的Spring依赖注入的步骤,用两个例子来推导一下整个过程,举例子有助于理解假相。
先用一个最简略的例子:没有依赖的单例bean的创立。
推导过程是须要上一篇文章的步骤的,要参照步骤一步一步来。
无依赖的单例Bean的创立
假如要创立单例bean A:
- 首先,getBean->deGetBean办法,调用getSingleton(beanName,true)办法。
- getSingleton(beanName,true)一次查看一级、二级、三级缓存,都没有A对象,返回null。
- 查看Dependon,假如没有设置,不须要创立DependOn对象。
- 调用getSingleton(beanName,factory)办法:查看一级缓存中不存在,将以后bean的name放入“正在创立中”列表,调用createBean创立bean。
- createBean创立A的实例,查看到以后bean在“正在创立中”列表中,则将以后bean放入三级缓存中。
- 调用populateBean进行属性填充,因为A对象没有依赖任何对象,所以不须要注入其余对象,间接实现属性填充。
- 调用返回到第4步getSingleton(beanName,factory)办法中,实现bean创立后,将以后bean name从“正在创立中”列表中移除。
- 将bean A从三级缓存、二级缓存中移除,放入一级缓存中。
- 实现bean A的创立。
循环依赖的单例Bean的创立过程
A依赖B,B依赖A,假如都是属性的相互依赖,即:
@Componentpublic class A { @Autowired private B b;}
@Componentpublic class B { @Autowired private A a;}
集体认为简单的循环依赖都能够转化为我依赖你、你依赖我这种模式,所以咱们还是试图把这个例子说的分明明确一点,关键步骤用图示的形式阐明。
假如首先创立A实例。
- 执行到getSingleton(beanName,boolean)办法的时候,三个缓存都空:
- 而后,接着执行到doCreateBean的时候,会把A的工厂办法放入到三级缓存,如图:
- 接下来就是populateBean办法,为bean A执行属性填充,查找到须要注入bean B,调用getBean,如图,用蓝色箭头示意,当执行到getSingleton(beanName,boolean)办法的时候,三个缓存中都没有bean B:
- 继续执行到doCreateBean的时候,会把B的工厂办法放入到三级缓存:
- 而后到populateBean办法,为bean B执行属性填充,查找到须要注入bean A。
- 调用getBean(A),如图,用红色箭头示意,当执行到getSingleton(beanName,boolean)办法的时候,三级缓存中存在bean A,所以,利用工厂办法创立A对象,放入二级缓存,返回bean A,并将A从三级缓存移除:
- 返回到步骤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的创立。
- 流程返回到第3部,bean A的populateBean办法获取到了曾经实现创立的bean B对象,实现Bean A的属性注入。
- 之后继续执行bean A的doCreateBean的后续逻辑,实现Bean A的创立,将Bean A放入到一级缓存,并从二级、三级缓存移除:
- 实现bean A和bean B的创立,实现A、B之间的依赖注入。
小结
用图解的形式阐明Spring通过三级缓存解决依赖注入的过程。其实集体了解,对于更加简单的依赖关系,注入过程无非就是在以上10个步骤之间一直递归调用的过程。
据说有一个问题是,Spring三级缓存的必要性,前面的文章会尝试答复这个问题。
上一篇 Spring FrameWork从入门到NB -三级缓存解决循环依赖底细 (一)