美文网首页
spring如何解决循环依赖

spring如何解决循环依赖

作者: 铜炉 | 来源:发表于2021-01-07 20:03 被阅读0次

    什么是循环依赖

    循环依赖指的是两个bean互相依赖彼此,beanA在示例化的时候要注入beanB,beanB在实例化的时候要注入beanA,导致两者互相依赖谁都不能实例化成功的情况。

    image.png

    但是,在spring中,如果我们创建了两个bean,彼此注入对方,在spring上下文初始化的时候却可以帮我们构建出两个完成体的springbean,那spring是怎么做到的呢?

    解决循环依赖的方法

    在实际探索源码的过程中,发现spring解决这个问题主要是采用了三级缓存解决了彼此依赖的问题,下面让我们回顾一下流程。
    首先,定义两个bean

    package com.zt.beans;
    
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Component;
    
    @Component
    public class TestBeanA {
        @Autowired
        TestBeanB testBeanB;
    }
    
    package com.zt.beans;
    
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Component;
    
    @Component
    public class TestBeanB {
        @Autowired
        TestBeanA testBeanA;
    }
    

    可以看到,beanA和beanB互相持有彼此,接下来我们通过ApplicationContext获取testBeanA。

    import org.junit.Test;
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.annotation.AnnotationConfigApplicationContext;
    
    public class CircleDependTest {
        @Test
        public void testCircleDepend() {
            ApplicationContext applicationContext = new AnnotationConfigApplicationContext("com.zt.beans");
            Object testBeanA = applicationContext.getBean("testBeanA");
            System.out.println(testBeanA);
        }
    }
    

    输出结果


    image.png

    TestBeanA创建成功。

    三级缓存

    一级缓存:singletonObjects 存储构建完成的spring bean对象
    二级缓存:earlySingletonObjects 存储三级缓存加工过的对象,此时spring bean 还未构建完成
    三级缓存:singletonFactories 存储刚刚构建的bean工厂,实际是一个回调函数。

    BeanA构建流程

    1、调用beanA的无参构造方法,将beanA放入三级缓存中,标记beanA正在构建中
    2、为beanA属性赋值,此时发现,beanA依赖于beanB,从IOC容器中获取beanB
    3、beanB此时还为构建,调用beanB的无参构造方法,将beanB放入三级缓存中
    4、为beanB属性赋值,此时发现,beanB依赖于beanA,从IOC容器中获取beanA
    5、beanA此时正在构建中,从三级缓存中获取beanA,将beanA从三级缓存移除,放入二级缓存中(此步骤可以拓展)
    6、将未完全构建完成的beanA赋值给beanB,beanB构建完成,讲beanB放入一级缓存中,并清空二级、三级缓存中的beanB(此步骤spring会统一再次清空缓存)
    7、beanA获取到构建完成的beanB,讲beanB赋值给beanA,beanA构建完成,将beanA放入一级缓存中,beanA构建完成。

    相关文章

      网友评论

          本文标题:spring如何解决循环依赖

          本文链接:https://www.haomeiwen.com/subject/icftaktx.html