Spring源码浅析の循环依赖

AbstractBeanFactory#doGetBean:尝试获取bean

如果bean是单例的:

if (mbd.isSingleton()) {
	//尝试获取bean <一>
	sharedInstance = getSingleton(beanName, () -> {
		try {
			//获取不到就创建
			return createBean(beanName, mbd, args);
		}
		catch (BeansException ex) {
			// Explicitly remove instance from singleton cache: It might have been put there
			// eagerly by the creation process, to allow for circular reference resolution.
			// Also remove any beans that received a temporary reference to the bean.
			destroySingleton(beanName);
			throw ex;
		}
	});
	//然后再次获取
	bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
	
	...	
}

<一>
DefaultSingletonBeanRegistry#getSingleton 方法
先从单例池中获取:Object singletonObject = this.singletonObjects.get(beanName);
如果获取不到就去创建一个:singletonObject = singletonFactory.getObject(); 实际调用的是AbstractBeanFactory#createBean <二>
然后放入单例池 addSingleton(beanName, singletonObject);

<二>
重点是 Object beanInstance = doCreateBean(beanName, mbdToUse, args);

AbstractAutowireCapableBeanFactory#doCreateBean的逻辑:

  • 实例化对象:AbstractAutowireCapableBeanFactory#createBeanInstance
  • 解决循环依赖:
boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
		isSingletonCurrentlyInCreation(beanName));
if (earlySingletonExposure) {
	if (logger.isTraceEnabled()) {
		logger.trace("Eagerly caching bean '" + beanName +
				"' to allow for resolving potential circular references");
	}
	addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));<>
}

<三>

protected void addSingletonFactory(String beanName, ObjectFactory<?> singletonFactory) {
		Assert.notNull(singletonFactory, "Singleton factory must not be null");
		锁单例池,防止并发
		synchronized (this.singletonObjects) {
			单例池中找不到当前bean
			if (!this.singletonObjects.containsKey(beanName)) {
				在三级缓存中放入 k:当前bean名称 value 工厂
				this.singletonFactories.put(beanName, singletonFactory);
				二级缓存删除当前bean的名称
				this.earlySingletonObjects.remove(beanName);
				保存当前已经注册单例bean的名称
				this.registeredSingletons.add(beanName);
			}
		}
	}
  • 属性赋值:AbstractAutowireCapableBeanFactory#populateBean
  • 初始化:AbstractAutowireCapableBeanFactory#initializeBean

循环依赖:A和B两个实例,A的属性是B,B的属性是A
前提条件,A和B都是单例的。假设目前要初始化A:
1、AbstractBeanFactory#doGetBean 尝试获取A
2、获取不到,AbstractBeanFactory#createBean 创建A
 2.1、实例化A
 2.2、解决循环依赖:在三级缓存中放入k:a,V:A的工厂
 2.3、设置属性,发现需要B
  2.3.1、AbstractBeanFactory#doGetBean 尝试获取B
  2.3.2、获取不到,AbstractBeanFactory#createBean 创建B
   2.3.2.1、实例化B
   2.3.2.2、解决循环依赖:在三级缓存中放入k:b,V:B的工厂
   2.3.2.3、设置属性,发现需要A,再次调用AbstractBeanFactory#doGetBean(在AbstractAutowireCapableBeanFactory#autowireByNamegetBean) ,走Object sharedInstance = getSingleton(beanName);<四>
   2.3.2.4、初始化B,DefaultSingletonBeanRegistry#addSingleton 中将B放入一级缓存,删除二级缓存
 2.4、初始化A,DefaultSingletonBeanRegistry#addSingleton 中将A放入一级缓存,删除二级缓存

<四>

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) {
				ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
				//根据bean的名称找到bean工厂
				if (singletonFactory != null) {
					//创建bean
					singletonObject = singletonFactory.getObject();
					//放入二级缓存
					this.earlySingletonObjects.put(beanName, singletonObject);
					//从三级缓存中清除
					this.singletonFactories.remove(beanName);
				}
			}
		}
	}
	//返回bean的实例
	return singletonObject;
}

小结

doGetBean中有两个getSingleton方法,第一个用于解决依赖循环问题,第二个只有一级缓存中没有对应bean的时候,才会调用createBean,实例化,向三级缓存中提前曝光。属性设置,初始化都是在createBean中的

下一篇:读取xml配置注册成bean
下下篇:refresh全过程

你可能感兴趣的:(源码分析,spring,java,后端,spring,boot)