Spring三级缓存和循环依赖

解决循环依赖

一般都是通过属性注入解决循环依赖,简单来说就是先创建对象A,然后在为对象设置属性B,在初始化B时当发生循环依赖时,可以使用未完全初始化的对象A设置到B的属性。所以一个简单的实现就是将创建的半成品A先保存在缓存中,然后B依赖A时先使用缓存中的半成品A进行初始化,B正常初始化并注入到bean容器中。接着A也可以完成初始化也被加入到bean容器中并删除缓存的半成品。如果把bean容器也看做成功初始化bean的缓存,那么上面这个解决循环依赖的方案就是用了二级缓存。

AOP对循环依赖的影响

Spring中可能需要为类生产代理对象,一般情况下Spring都是在bean创建完成之后才创建代理对象,而在上面的方案中半成品A需要被提前注入到对象B中,这时应该生成A的代理对象然后将其作为属性注入到B中。生成代理的时机有两种:

  1. 对所有类都提前创建代理对象并放入缓存。
  2. 在发生循环依赖时创建代理对象。

Spring选择了后者,为了防止重复创建代理对象,将发生循环依赖的代理对象放入到一个缓存中,也就是earlySingletonObjects中,在A对象完成初始化之后在earlySingletonObjects中找到生成好的代理对象即可。Spring在这里引入了earlySingletonObjects作为代理对象的缓存,也就形成了Spring的三级缓存结构。

  1. 因循环依赖而需要提前使用的半成品缓存。
  2. 半成品的代理对象缓存。
  3. 最终完成初始化的bean缓存
Bean在缓存中流转过程
  1. AbstractBeanFactory中根据beanName查找缓存的bean,如果没有创建则先创建,然后添加到缓存中。

    protected <T> T doGetBean(
    			String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly)
    			throws BeansException {
        String beanName = transformedBeanName(name);
        Object bean;
        // 在缓存根据beanName查找创建完成的bean,如果产生循环依赖(singletonFactory中有半成品对象A),则对其代理后加入代理对象缓存中并返回。
        Object sharedInstance = getSingleton(beanName);
        if (sharedInstance != null && args == null) {
    		bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
        }
        else {
            // Create bean instance.
            if (mbd.isSingleton()) {
                sharedInstance = getSingleton(beanName, () -> {
                    return createBean(beanName, mbd, args);
                });
                bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
            }	
        }
        return (T) bean;
    }
    
    protected Object getSingleton(String beanName, boolean allowEarlyReference) {
    		Object singletonObject = this.singletonObjects.get(beanName);
    		if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
    			synchronized (this.singletonObjects) {
    				singletonObject = this.earlySingletonObjects.get(beanName);
    				if (singletonObject == null && allowEarlyReference) {
                        // 从半成品缓存中拿出包装好的对象A,这里通过之前传入的工厂方法获得代理对象。
    					ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
    					if (singletonFactory != null) {
    						singletonObject = singletonFactory.getObject();
    						this.earlySingletonObjects.put(beanName, singletonObject);
    						this.singletonFactories.remove(beanName);
    					}
    				}
    			}
    		}
    		return singletonObject;
    	}
    
  2. DefaultSingletonBeanRegistry使用工厂方法创建bean,并将bean添加到bean容器的缓存中。

    public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
        Object singletonObject = this.singletonObjects.get(beanName);
    	if (singletonObject == null) {
            // 工厂方法调用AbstractAutowireCapableBeanFactory创建bean
            singletonObject = singletonFactory.getObject();
            newSingleton = true;
    
            if (newSingleton) {
    			addSingleton(beanName, singletonObject);
    		}
        }		
        return singletonObject;
    }
    
    protected void addSingleton(String beanName, Object singletonObject) {
    	synchronized (this.singletonObjects) {
            // 将创建完成的对象加入bean容器缓存中,并释放其他缓存
    		this.singletonObjects.put(beanName, singletonObject);
    		this.singletonFactories.remove(beanName);
    		this.earlySingletonObjects.remove(beanName);
    		this.registeredSingletons.add(beanName);
    	}
    }
    
  3. AbstractAutowireCapableBeanFactory创建bean处理循环依赖,创建循环依赖的代理对象。

protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) 
    throws BeanCreationException {
	Object bean = instanceWrapper.getWrappedInstance(); // 创建原始bean对象A
	if (earlySingletonExposure) {
			if (logger.isTraceEnabled()) {
				logger.trace("Eagerly caching bean '" + beanName +
						"' to allow for resolving potential circular references");
			}
			// 将原始bean对象A,加入缓存,这里对bean进行了一个包装,用于之后生成代理对象
			addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
		}
	// 省略初始化对象A的代码
   
    // 对象A初始化完成
    Object exposedObject = bean;
    // 在代理对象缓存中取出已经生成的代理对象,并进行判断防止重复代理
    Object earlySingletonReference = getSingleton(beanName, false);
    if (earlySingletonReference != null) {
        if (exposedObject == bean) {
            exposedObject = earlySingletonReference;
        }
    }

    return exposedObject;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值