Spring怎么解决循环依赖的问题?

spring bean有两种 注入方式

对于构造器注入的循环依赖,Spring处理不了,会直接抛出BeanCurrentlylnCreationException异常。

对于属性注入的循环依赖(单例模式下),是通过三级缓存处理来循环依赖的。

singletonObjects 一级缓存 主要存放Spring完整生命周期的单例bean

earlySingletonObjects二级缓存 主要存放完成实例化未初始化的单例对象map,bean name -->

singletonFactories : 单例对象工厂map,bean name --> ObjectFactory,单例对象实例化完成之后会加入singletonFactories

spring 容器在获取bean的时候首先从一级缓存总获取,获取不到,到二级缓存获取,如果获取不到到三级缓存获取,如果从三级缓存获取到了就会从三级缓存中删除缓存,然后将从三级缓存获取的半成品bean放到二级缓存

protected Object getSingleton(String beanName, boolean allowEarlyReference) {
	//从一级缓存中获取
	Object singletonObject = this.singletonObjects.get(beanName);
	//若一级缓存中没有,且当前bean正在创建中
	if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
		synchronized (this.singletonObjects) {
			//从二级缓存中获取
			singletonObject = this.earlySingletonObjects.get(beanName);
			/**
			 * 二级缓存中没有,且允许循环依赖
			 *二级缓存作用:若涉及到三个及以上对象循环依赖,此时就可以直接从二级缓存中获取到值
			 */
			if (singletonObject == null && allowEarlyReference) {
				//从三级缓存中获取,这里获取到的是一个对象工厂
				ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
				if (singletonFactory != null) {
					/**
					 * 从对象工厂中获取到一个半成品bean
					 */
					singletonObject = singletonFactory.getObject();
					//放入到二级缓存
					this.earlySingletonObjects.put(beanName, singletonObject);
					//从三级缓存中移除
					this.singletonFactories.remove(beanName);
				}
			}
		}
	}
	return singletonObject;
}

在获取bean的时候,添加三级缓存

	boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
				isSingletonCurrentlyInCreation(beanName));
		if (earlySingletonExposure) {
			if (logger.isDebugEnabled()) {
				logger.debug("Eagerly caching bean '" + beanName +
						"' to allow for resolving potential circular references");
			}
			addSingletonFactory(beanName, new ObjectFactory() {
				@Override
				public Object getObject() throws BeansException {
					return getEarlyBeanReference(beanName, mbd, bean);
				}
			});
		}
 
  

                            
                        
                    
                    
                    

你可能感兴趣的:(框架,面试题,学习记录,spring,java,后端)