一、Spring Bean创建流程总结
(一)BeanFactory:容器根接口
(二)registerDisposableBeanIfNecessary(beanName, bean, mbd)
Spring容器中创建的bean经过实例化、初始化之后得到完整的bean实例对象,在返回该对象之前需要进一步注册bean以方便后续在容器销毁的时候销毁对象。
(三)Bean的生命周期
二、Spring Bean的循环依赖问题
(一)循环依赖流程图及三级缓存改造思路
Spring容器中需要获取bean对象时,先从一级缓存中获取,一级缓存中没有取到对象则从二级缓存中获取,二级缓存也没有对象则从三级缓存中取。
一级缓存中存放的是完整的bean对象(实例化且完成初始化);二级缓存中存放半成品的bean对象(在堆内存开辟存储空间存储bean对象,此时对象的属性值是默认值因为还没有初始化);三级缓存中存放λ表达式。如果有bean需要提前初始化其依赖的bean则取出三级缓存中的***λ表达式(单例对象工厂)***来创建被依赖bean的半成品单例对象,并将创建好的半成品单例对象存放到二级缓存,同时移除三级缓存中的存放的被依赖的beanName对应的λ表达式。二级缓存中的bean初始化完成后存入一级缓存,同时根据bean名称移除二级缓存中的半成品bean。
(二)解决循环依赖问题涉及到的重要方法
1.addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean))
doCreateBean方法是Spring容器中创建bean时必须调用的方法,通过该方法可以创建一个完整的bean对象(实例化且完成初始化)。bean实例化完成后需要填充属性和初始化然后才会得到一个完整的bean对象。如果该实例化bean是单例并且允许循环引用并且该单例bean正处于创建阶段,那么在填充属性和初始化之前需要调用addSingletonFactory方法将该bean对应的单例对象工厂添加进三级缓存,当后期存在其他bean该bean时,从三级缓存中取出被依赖bean的单例对象工厂然后创建被依赖bean的实例对象并存放在二级缓存中,通过这种方式将被依赖bean提前实例化并暴漏给其他bean使用。
虽然通过三级缓存中的单例对象工厂创建出来的bean对象是未初始化的半成品bean对象,但是仍然可以让其他依赖该bean的bean使用以便其完成实例化。
(三)循环依赖测试
1.代码
public class A {
private String name;
private B b;
public B getB() {
return b;
}
public void setB(B b) {
this.b = b;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "A{" +
"b=" + b +
'}';
}
}
public class B {
// private C c;
//
// public C getC() {
// return c;
// }
//
// public void setC(C c) {
// this.c = c;
// }
private A a;
public A getA() {
return a;
}
public void setA(A a) {
this.a = a;
}
// @Override
// public String toString() {
// return "B{" +
// "a=" + a +
// '}';
// }
}
public class C {
private A a;
public A getA() {
return a;
}
public void setA(A a) {
this.a = a;
}
}
2.xml配置