spring的循环依赖

spring中的三个缓存

singletonObjects, earlySingletonObjects, singletonFactories

  • 调用getBean方法是访问缓存的顺序:singletonObjects, earlySingletonObjects, singletonFactories
  • 访问缓存的条件:
    • singletonObjects(始终允许访问)
    • earlySingletonObjects(singletonObjects返回null 且bean正在创建)
    • singletonFactories(earlySingletonObjects返回null 且允许循环依赖)
  • 把一个bean放入缓存的先后顺序:singletonFactories、earlySingletonObjects、singletonObjects
创建bean的几个阶段
  • 1、先从缓存中获取bean返回null。getSingleton(beanName);
  • 2、标记为正在创建的bean。markBeanAsCreated(beanName);
  • 3、准备创建bean。拉姆达 -> return createBean(beanName, mbd, args);
  • 4、创建半成品bean。AbstractAutowireCapableBeanFactory#doCreateBean
  • 5、把半成品bean封装为ObjectFactory<?>并存放到singletonFactories缓存中
  • 6、开始填充属性。populateBean(beanName, mbd, instanceWrapper);
  • 7、初始化。exposedObject = initializeBean(beanName, exposedObject, mbd);
  • 8、比对bean、重新赋值
  • 9、返回bean,放入singletonObjects

循环依赖

循环依赖发生在属性填充 6-阶段。A和B相互依赖且先创建A,看看循环依赖是如何产生的

A进行属性填充之前已经把半成品放入了singletonFactories中,进入第6阶段:

  • A填充B属性时发现singletonObjects没有B。(不具备访问其他两个map的条件)
  • 需要重新创建B,创建B需要走上面的几个阶段 入栈······
  • B也创建半成品,缓存办成品到singletonFactories
  • B也开始填充属性···
  • B填充AsingletonObjects中没有A,但是A正在创建且允许循环引用,最终在singletonFactories中发现了A。
  • B开始调用singletonFactories创建A的完整对象并放入earlySingletonObjects
  • 把A填充到B的属性中,至此B创建完成,出栈······
  • B创建完给A的属性赋值
    继续第七阶段:
  • 半成品初始化(很重要…)
  • 比对(半成品初始化后A的和earlySingletonObjects中的A比对)

Java不是引用传递吗?对象应该都是同一个啊?为什么要比对?

答案是:半成品对象和代理对象不是同一个对象

spring创建代理对象的时机

属性填充后的初始化阶段

如果一个类没有循环引用且这个类需要创建代理对象,那么这个类的代理对象会在这个阶段创建。也就是这个方法AbstractAutowireCapableBeanFactory#initializeBean()

protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd) {
	Object wrappedBean = bean;
	if (mbd == null || !mbd.isSynthetic()) {
		// 就是这里调用后置处理器
		wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
	}
	return wrappedBean;
}
// 就是这个后置处理器AbstractAutoProxyCreator#postProcessAfterInitialization
public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
    if (bean != null) {
        Object cacheKey = this.getCacheKey(bean.getClass(), beanName);
        // earlyProxyReferences如果存在就不创建代理对象了???很重要
        if (this.earlyProxyReferences.remove(cacheKey) != bean) {
			// 开始创建代理对象
            return this.wrapIfNecessary(bean, beanName, cacheKey);
        }
    }
    return bean;
}
循环依赖阶段
// earlyProxyReferences如果存在就不创建代理对象了???很重要
if (this.earlyProxyReferences.remove(cacheKey) != bean) {
// 开始创建代理对象
    return this.wrapIfNecessary(bean, beanName, cacheKey);
}

cacheKey是哪个方法往这个earlyProxyReferences中put的?


// 创建bean的第五个阶段(填充属性之前,循环依赖之前)
addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));

// 循环依赖阶段
ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
singletonFactory.getObject();

// put阶段
public Object getEarlyBeanReference(Object bean, String beanName) {
    Object cacheKey = this.getCacheKey(bean.getClass(), beanName);
    this.earlyProxyReferences.put(cacheKey, bean);
    return this.wrapIfNecessary(bean, beanName, cacheKey);
}

在这里插入图片描述

代码

// 入口
================AbstractBeanFactory.doGetBean=================
{
    // DefaultSingletonBeanRegistry.getSingleton(String, ObjectFactory<?>)
    sharedInstance = getSingleton(beanName, () -> {
        try {
            // AbstractAutowireCapableBeanFactory.createBean(String, RootBeanDefinition, Object[])
            return createBean(beanName, mbd, args);
        });
    }
}

========= DefaultSingletonBeanRegistry.getSingleton(λ工厂) ===========
{
    //访问单例缓存,返回空
    Object singletonObject = this.singletonObjects.get(beanName);

    if (singletonObject ==null) {
        beforeSingletonCreation(beanName);  // 标记为正在创建
        singletonObject = singletonFactory.getObject();  // 调用λ工厂
        return singletonObject;
    }
    //循环依赖解决完成之后才会执行这里。
    afterSingletonCreation(beanName);
    addSingleton(beanName, singletonObject);
}

================= λ 中的createBean=======
================= 即singletonFactory.getObject()=================
================= 即AbstractAutowireCapableBeanFactory.doCreateBean =================
{
    Object beanInstance = doCreateBean(beanName, mbdToUse, args) {

        // 半成品wrapper
        instanceWrapper = createBeanInstance(beanName, mbd, args);
        // 获取半成品
        final Object bean = instanceWrapper.getWrappedInstance();

        // === 封装为factory返回缓存起来===
        // 条件this.allowCircularReferences默认值是true,填充属性阶段这个值为false
        // 从用户getBean开始这个值一直是默认值true,直到填充属性时spring源码调用getBean(beanName,false)
        // 这个false就是不允许循环引用了
        (mbd.isSingleton()&& this.allowCircularReferences && isSingletonCurrentlyInCreation(beanName)) {

            // 缓存半成品,循环依赖就是借助这个factory
            addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean)) {
                synchronized (this.singletonObjects)
                if (!this.singletonObjects.containsKey(beanName)){
                    this.singletonFactories.put(beanName, singletonFactory);
                    this.earlySingletonObjects.remove(beanName);
                    this.registeredSingletons.add(beanName);
                }
            }
        }
        // 暴露bean
        Object exposedObject = bean;
        //属性填充(允许循环依赖,下面接着创建依赖的bean)
        populateBean(beanName, mbd, instanceWrapper);
        exposedObject = initializeBean(beanName, exposedObject, mbd);

        // 属性填充就是后置处理器的事情了(为属性创建实例、属性循环依赖、使用singletonFactories缓存解决依赖、等等)
        // 下面就不允许循环依赖了(至此singletonFactories缓存的使用已经完成了)
    }


    // 比较阶段:() -> getEarlyBeanReference(beanName, mbd, bean);
    // 这个拉姆达表达式的功劳,第三个参数:拉姆达持有bean,会对这个bean进一步加工(循环依赖阶段:otherBean -> factory.getObject(bean))

    Object earlySingletonReference = getSingleton(beanName, false);
    if (earlySingletonReference != null) {
        if (exposedObject == bean) {
            exposedObject = earlySingletonReference;
        }

}




{
    // 理解
    simpleBean {  // 同一个simpleBean对象(引用相同)
        1、singletonFactories(simpleBean) 先放入factory
        2、填充属性(simpleBean)  ===> 获取factory进一步加工 ===> 结果就是 simpleBean变成enhancedBean,一个新的代理对象地址不一样
                                earlySingletonObjects.put(enhancedBean)
        3、init(simpleBean)
    
        // 比较阶段
        simpleBean已经过时了,重新赋值 simpleBean = enhancedBean
        返回simpleBean。
    
    
        exposedObject == simpleBean
        earlySingletonReference == enhancedBean
        把这个方法看会 AbstractAutowireCapableBeanFactory.doCreateBean 循环引用也就理解的差不多了
        循环引用至此完结!
    }
}



========= 三个缓存
// 访问单例缓存
singletonObject = singletonObjects.get(beanName);
// 访问factory.getObject()返回对象的缓存
if(singletonObject== null && 正在创建){
    singletonObject = earlySingletonObjects.get(beanName);
    if(singletonObject == null && 允许循环引用阶段){
    // 访问factory缓存、继续创建对象
    ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
        if (singletonFactory!=null){
            singletonObject = singletonFactory.getObject();
            this.earlySingletonObjects.put(beanName, singletonObject); I
            this.singletonFactories.remove(beanName);
        }



=========== A<=>B相互依赖
=========== A<=>B相互依赖
--  singletonFactories: 存放办成品的A, 然后创建B。B又依赖A,从factory中取出A继续创建A。把A放到earlySingletonObjects中
--  earlySingletonObjects:factory继续加工的bean
--  singletonObjects:B创建完成之后继续A的流程,这个流程流程就是对比阶段。
    对比阶段把最终的bean放进singletonObjects,aka:factory继续加工的bean
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值