spring如何解决循环依赖

什么是循环依赖

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

spring如何解决循环依赖_第1张图片
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);
    }
}

输出结果


spring如何解决循环依赖_第2张图片
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如何解决循环依赖)