开始用上一篇文章讲到的 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,假如都是属性的相互依赖,即:
@Component
public class A {
@Autowired
private B b;
}
@Component
public 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 - 三级缓存解决循环依赖底细(一)