源码解析spring是如何解决循环依赖的

214 阅读3分钟

源码解析spring是如何解决循环依赖的

一、什么是循环依赖?

循环依赖是指在beanA中注入了beanB,在beanB中注入了beanA,因此在创建BeanA时,需要先初始化依赖对象beanB,在创建BeanB时需要先初始化依赖对象beanA,如此产生循环反复的过程。

图片1.png

图片4.png

图片5.png

二、spring中解决循环依赖的三级缓存

1、singletonObjects :一级缓存,保存实例化且初始化完成的实例
2、earlySingletonObjects:二级缓存,保存实例化,但是还未初始化完成实例
3、singletonFactories :三级缓存,保存bean工厂,解决循环依赖的关键

三、过程分析

图片6.png

源码解析:

1、创建bean实例的方法

protected <T> T doGetBean(

String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly)throws BeansException {

................

Object sharedInstance = getSingleton(beanName);

if (sharedInstance != null && args == null) {

...........

}

else {

..............

if (mbd.isSingleton()) {

sharedInstance = getSingleton(beanName, () -> {

try {

return createBean(beanName, mbd, args);

}catch (BeansException ex) {

throw ex;

}

});

beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);

}

}

我们只需要看主要的两个方法,一个时没有回调函数的getSingleton()方法和一个有回调函数createBean()的getSingleton()方法。其中第一个getSingleton方法即是从一、二、三、级缓存中获取实例。第二个有回调函数的getSington即是真正的创建bean实例的方法。二、从缓存中获取实例

2、从缓存中获取实例
从缓存中获取实例的方法就是上面说的第一个getSington()

protected Object getSingleton(String beanName, boolean allowEarlyReference) {

    Object singletonObject = this.singletonObjects.get(beanName);

    if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {

        singletonObject = this.earlySingletonObjects.get(beanName);

        if (singletonObject == null && allowEarlyReference) {

            synchronized (this.singletonObjects) {

                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) {

                      singletonObject = singletonFactory.getObject();

                      this.earlySingletonObjects.put(beanName, singletonObject);

                      this.singletonFactories.remove(beanName);

                    }

               }

            }

        }

    }

}

 return singletonObject;

}

我们可以看到此方法会先从一级缓存singletonObjects中获取实例对象,如果存在则返回,不存在继续从二级缓存earlySingletonObjects中获取对象实例,如果存在则返回,不存在则继续从三级缓存singletonFactories获取对象实例,如果不存在则直接返回null,存在则会将三级缓存中的对象实例拿出来放到二级缓存中,并将该实例从三级缓存中移除。我们一开始创建实例时肯定时三个级别的缓存中都没办法获取得到实例的,因此直接返回null,继续走创建实例的方法。 3、开始创建对象实例 真正创建对象实例的方法是在一中有回调函数的那个getSingleton方法

		synchronized (this.singletonObjects) {
			Object singletonObject = this.singletonObjects.get(beanName);
			if (singletonObject == null) {
				if (this.singletonsCurrentlyInDestruction) {
					throw new BeanCreationNotAllowedException(beanName,"Singleton bean creation not allowed while singletons of this factory are in destruction " +"(Do not request a bean from a BeanFactory in a destroy method implementation!)");
				}
				beforeSingletonCreation(beanName);
				boolean newSingleton = false;
				boolean recordSuppressedExceptions = (this.suppressedExceptions == null);
				if (recordSuppressedExceptions) {
					this.suppressedExceptions = new LinkedHashSet<>();
				}
				try {
					singletonObject = singletonFactory.getObject();
					newSingleton = true;
				}
				catch (IllegalStateException ex) {
					singletonObject = this.singletonObjects.get(beanName);
					if (singletonObject == null) {
						throw ex;
					}
				}
				catch (BeanCreationException ex) {
					if (recordSuppressedExceptions) {
						for (Exception suppressedException : this.suppressedExceptions) {
							ex.addRelatedCause(suppressedException);
						}
					}
					throw ex;
				}
				finally {
					if (recordSuppressedExceptions) {
						this.suppressedExceptions = null;
					}
					afterSingletonCreation(beanName);
				}
				if (newSingleton) {
					addSingleton(beanName, singletonObject);
				}
			}
			return singletonObject;
		}

我们只需要关注里面比较重要的两个步骤

1、singletonObject = singletonFactory.getObject();

2、addSingleton(beanName, singletonObject);

步骤1这里就是会执行回调方法createBean()方法里面的doCreateBean()方法进行创建对象实例,我们看看这个方法做了什么

protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
			throws BeanCreationException {
		// Instantiate the bean.
		BeanWrapper instanceWrapper = null;
		.....
		Object bean = instanceWrapper.getWrappedInstance();
		Class<?> beanType = instanceWrapper.getWrappedClass();
		......
		......
		boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
			....
			addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
		}
				Object exposedObject = bean;
		try {
			populateBean(beanName, mbd, instanceWrapper);
			exposedObject = initializeBean(beanName, exposedObject, mbd);
		}
		catch (Throwable ex) {
			.....
			}
		}
	    .....
		return exposedObject;
	}

在这里我们需要关注的两个方法addSingletonFactory和populateBean。addSingletenFactory这个方法就是把实例化的bean放进了三级缓存singletonFactories中,我们看看里面的代码

protected void addSingletonFactory(String beanName, ObjectFactory<?> singletonFactory) {
		Assert.notNull(singletonFactory, "Singleton factory must not be null");
		synchronized (this.singletonObjects) {
			if (!this.singletonObjects.containsKey(beanName)) {
				this.singletonFactories.put(beanName, singletonFactory);
				this.earlySingletonObjects.remove(beanName);
				this.registeredSingletons.add(beanName);
			}
		}
}

而populateBean这个方法正式初始化bean依赖注入对象的方法,通过层层解析,找到polulateBean这个方法中调用了applyPropertyValues这个方法,而这个方法调用了resolveValueIfNecessary方法,这个方法中通过调用resolveReference来处理依赖bean对象

@Nullable
	private Object resolveReference(Object argName, RuntimeBeanReference ref) {
		try {
			Object bean;
			Class<?> beanType = ref.getBeanType();
			if (ref.isToParent()) {
				BeanFactory parent = this.beanFactory.getParentBeanFactory();
				if (parent == null) {
					........
				}
				if (beanType != null) {
					bean = parent.getBean(beanType);
				}
				else {
					bean = parent.getBean(String.valueOf(doEvaluate(ref.getBeanName())));
				}
			}
			else {
				String resolvedName;
				if (beanType != null) {
					NamedBeanHolder<?> namedBean = this.beanFactory.resolveNamedBean(beanType);
					bean = namedBean.getBeanInstance();
					resolvedName = namedBean.getBeanName();
				}
				else {
					resolvedName = String.valueOf(doEvaluate(ref.getBeanName()));
					bean = this.beanFactory.getBean(resolvedName);
				}
				this.beanFactory.registerDependentBean(resolvedName, this.beanName);
			}
			if (bean instanceof NullBean) {
				bean = null;
			}
			return bean;
		}
		catch (BeansException ex) {
			....
		}
	}

这里又会通过 this.beanFactory.getBean(resolvedName);这段代码去创建依赖对象,而getBean方法里面又是回到步骤一中调用doGetBean方法创建实例对象的逻辑。

@Override
	public Object getBean(String name) throws BeansException {
		return doGetBean(name, null, null, false);
	}

以上便是spring中解决循环依赖的全部过程。