天天看点

Spring初始化bean过程(三级缓存解决循环依赖)

三级缓存

//一级缓存,用来存放初始化完成的Bean,可对外提供使用,在
         final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);
        //二级缓存 ,用来提前暴露Bean,该缓存中的Bean还未完成自身的初始化过程,不可对外提供使用,待完成初始化后,会将该Bean放置一级缓存方可使用
         final Map<String, Object> earlySingletonObjects = new HashMap<>(16);
         //三级缓存 ,用来存放创建Bean的过程,对象工厂中主要是BeanPostProcessor的调用,aop的创建过程在该缓存中
        final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16);
           

现有Bean(A)、Bean(B)需要创建

A中有一个属性B

B中有一个属性A(循环依赖)

下面是Spring创建Bean的过程

1.实例化一个A

2.将创建A的过程放入三级缓存(ObjectFactory)

3.初始化A中的属性

    3.1.需要注入B,去一二三缓存中找,没有找到

    3.2.实例化一个B

    3.3.将创建B的过程放入三级缓存(ObjectFactory)

    3.4.初始化B中的属性

        3.4.1.需要注入A,去缓存中找,一二三逐级查找,最终在三级缓存中找到创建A的方法

        3.4.2.调用该方法,拿到A的半成品,将半成品A放入二级缓存,删除三级缓存中的A,返回A

        3.4.3拿到半成品A注入到B中

    3.5.完成B的初始化,此时B中的属性A已完成注入(注入的是一个半成品A)

    3.6.去二级缓存中拿B,不能拿到对象,继续使用原有的B往后执行

    3.6.将B保存到一级缓存,同时清除二级、三级缓存中的B

    3.7.将完成品B返回,继续完成A中的属性B注入

4.完成A的初始化过程,此时A/B已经完成循环依赖

5.去二级缓存中拿A,能拿到对象,将二级缓存中的A替换前面的A,使用二级缓存中的A继续后续操作

6.将A保存到一级缓存,同时清除二级、三级缓存中的A

7.此时已完成Spring初始化Bean的循环依赖的全过程