Spring 循环依赖的解决

A依赖B B依赖A的场景

public class A {
    private B b;

    public void setB(B b) {
        this.b = b;
    }

    @Override
    public String toString() {
        return "A::toString";
    }
}
public class B {
    private A a;

    public void setA(A a) {
        this.a = a;
    }

    @Override
    public String toString() {
        return "B::toString";
    }
}

xml 配置

    <bean id="a" class="com.xiya.test.cricle.A">
        <property name="b" ref="b"/>
    </bean>

    <bean id="b" class="com.xiya.test.cricle.B">
        <property name="a" ref="a"/>
    </bean>

解决循环依赖的3个缓存

// org.springframework.beans.factory.support.DefaultSingletonBeanRegistry
    // 单例对象工厂的cache
    private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);
    // 提前暴光的单例对象的Cache
   	private final Map<String, Object> earlySingletonObjects = new HashMap<>(16);
    // 单例对象工厂的cache
	private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16);

    // 标识那个实例在创建中,判断是否存在循环依赖
    private final Set<String> singletonsCurrentlyInCreation = Collections.newSetFromMap(new ConcurrentHashMap<>(16));

org.springframework.beans.factory.support.AbstractBeanFactory#getBean(java.lang.String) ->
org.springframework.beans.factory.support.AbstractBeanFactory#doGetBean
所有的 getBean 都指向了 doGetBean 方法

org.springframework.beans.factory.support.AbstractBeanFactory#doGetBean
getBean(“a”): 第一次查a

  1. 执行 org.springframework.beans.factory.support.DefaultSingletonBeanRegistry#getSingleton(java.lang.String) 返回 null
    singletonObjects earlySingletonObjects singletonFactories 都为空
  2. 执行 sharedInstance = getSingleton(beanName, () -> {try { return createBean(beanName, mbd, args);}catch (BeansException ex) {destroySingleton(beanName);throw ex;}});

org.springframework.beans.factory.support.DefaultSingletonBeanRegistry#getSingleton(java.lang.String, org.springframework.beans.factory.ObjectFactory<?>)
3. 执行 org.springframework.beans.factory.support.DefaultSingletonBeanRegistry#beforeSingletonCreation 将实例a放入singletonsCurrentlyInCreation,表示a正在创建中
4. 执行 singletonFactory.getObject() 回调 getSingleton 方法的第二个参数 org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#createBean(java.lang.String, org.springframework.beans.factory.support.RootBeanDefinition, java.lang.Object[])
最终执行的 org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#doCreateBean

org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#doCreateBean
5. 执行 org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#createBeanInstance 此时a实例被创建出来(属性还没有设置)
6. 执行 addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
将实例a放入singletonFactories,singletonObjects earlySingletonObjects此时都为空
7. 执行 populateBean(beanName, mbd, instanceWrapper) 方法,设置a实例的属性
一系列无关操作过后最终还是执行 doGetBean 方法,获取b实例
org.springframework.beans.factory.support.BeanDefinitionValueResolver#resolveValueIfNecessary ->
org.springframework.beans.factory.support.BeanDefinitionValueResolver#resolveReference ->
最终执行 this.beanFactory.getBean(resolvedName)

执行完上述 getBean(“a”)
singletonFactories/singletonsCurrentlyInCreation包含a,singletonObjects earlySingletonObjects此时都为空

getBean(“b”): 第一次查b
8. 执行上述 1. 2.
9. 执行3.后singletonFactories包含a,singletonsCurrentlyInCreation包含a和b,singletonObjects earlySingletonObjects此时都为空
10. 执行上述 3. 4.
11. 执行5.后,b实例创建出来
12. 执行6.后,singletonFactories包含a和b,singletonsCurrentlyInCreation包含a和b,singletonObjects earlySingletonObjects此时都为空
13. 执行7. 因为 b依赖a,接着又去执行 doGetBean 方法,获取a实例

getBean(“a”): 第二次查a
14. 执行1.从 singletonFactories 三级缓存获取a实例,将其删除并放入二级缓存earlySingletonObjects
此时 singletonFactories只包含b,earlySingletonObjects包含a,singletonsCurrentlyInCreation包含a和b,singletonObjects 为空
getBean(“a”) 成功返回 a 实例

  1. 接着执行13.populateBean b 的属性a就注入进来了
  2. 执行 initializeBean(beanName, exposedObject, mbd) 初始化 b 实例
  3. 接着执行10.
  • 执行 afterSingletonCreation(beanName) singletonsCurrentlyInCreation删除b实例,此时 singletonFactories只包含b,earlySingletonObjects包含a,singletonsCurrentlyInCreation只包含a,singletonObjects 为空
  • 执行 addSingleton(beanName, singletonObject) singletonObjects放b实例,singletonFactories删除b实例
  • 此时 singletonFactories为空,earlySingletonObjects只包含a,singletonsCurrentlyInCreation只包含a,singletonObjects只包含b
  1. getBean(“b”) 执行完
  2. 接着执行7. a的实例b就注入进来了
  3. 执行 initializeBean(beanName, exposedObject, mbd) 初始化 a 实例
  4. 接着执行4.
  • 执行 afterSingletonCreation(beanName) singletonsCurrentlyInCreation删除a实例
  • 此时 singletonFactories为空,earlySingletonObjects只包含a,singletonsCurrentlyInCreation为空,singletonObjects只包含b
  • 执行 addSingleton(beanName, singletonObject),singletonObjects 放入 a实例,earlySingletonObjects删除a实例
  • 此时 singletonFactories earlySingletonObjects singletonsCurrentlyInCreation为空,singletonObjects包含a和b
  1. getBean(“a”) 执行完

这样看,二级缓存就可以解决循环依赖,为什么还需要多一级缓存?

再看a依赖b,a依赖c,b依赖a,c依赖a

假设只有 singletonFactories singletonObjects 二级缓存
getBean(“a”) a 放到 singletonFactories
getBean(“b”) b 放到 singletonFactories
getBean(“a”) 生成a实例,设置b的属性a,b实例化完成
getBean(“c”) c 放到 singletonFactories
getBean(“a”) 生成a实例,设置c的属性a,c实例化完成

这样导致a被生成了两次,不再是单例。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

N3verL4nd

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值