Spring源码-中级(二)-Bean创建流程总结及循环依赖问题

一、Spring Bean创建流程总结

(一)BeanFactory:容器根接口

BeanFactory的分支继承关系图

(二)registerDisposableBeanIfNecessary(beanName, bean, mbd)

Spring容器中创建的bean经过实例化、初始化之后得到完整的bean实例对象,在返回该对象之前需要进一步注册bean以方便后续在容器销毁的时候销毁对象。

(三)Bean的生命周期

Spring Bean的生命周期

二、Spring 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配置

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值