Spring的循环引用

本文根据Spring源码分析Spring中如何处理循环引用。

循环引用即A-B-A引用问题,关键在于如何解决创建A需要B,创建B需要A的问题,Spring中采用暴露未完成的Bean的方法实现循环引用。

tips:该方法并不能解决所有的循环引用问题,如构造器内的循环应用就无法解决。

Spring中包含三级缓存,这三级缓存在DefaultSingletonBeanRegistry中,是三个以BeanName为key的map

/** Cache of singleton objects: bean name to bean instance. */
private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);

/** Cache of singleton factories: bean name to ObjectFactory. */
private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16);

/** Cache of early singleton objects: bean name to bean instance. */
private final Map<String, Object> earlySingletonObjects = new ConcurrentHashMap<>(16);

缓存的查找过程在getSingleton方法中

protected Object getSingleton(String beanName, boolean allowEarlyReference) {
		// Quick check for existing instance without full singleton lock
        // 先找一级缓存
		Object singletonObject = this.singletonObjects.get(beanName);
		if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
            // 找二级缓存
			singletonObject = this.earlySingletonObjects.get(beanName);
			if (singletonObject == null && allowEarlyReference) {
				synchronized (this.singletonObjects) {
					// Consistent creation of early reference within full singleton lock
					singletonObject = this.singletonObjects.get(beanName);
                    // 双重检查
					if (singletonObject == null) {
						singletonObject = this.earlySingletonObjects.get(beanName);
						if (singletonObject == null) {
							ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
							if (singletonFactory != null) {
                                // 根据工厂获取Bean
								singletonObject = singletonFactory.getObject();
                                // 加入二级缓存
								this.earlySingletonObjects.put(beanName, singletonObject);
                                // 从三级缓存中删除
								this.singletonFactories.remove(beanName);
							}
						}
					}
				}
			}
		}
		return singletonObject;
	}

完成实例化后,会将一个工厂放入三级缓存,只有存工厂才能获得代理对象

protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
			throws BeanCreationException {

		// Instantiate the bean.
		...
		

		// Eagerly cache singletons to be able to resolve circular references
		// even when triggered by lifecycle interfaces like BeanFactoryAware.
        // 单例、允许循环引用、正在被创建
		boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
				isSingletonCurrentlyInCreation(beanName));
		if (earlySingletonExposure) {
            // 添加到三级缓存			
			addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
		}
}

此时如果产生循环依赖,会再次进入缓存查找过程,此时会找到缓存的A的工厂,根据工厂生产未完成的A,加入二级缓存,删除三级缓存中的A工厂,并返回未完成的A。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值