Spring迴圈依賴原理
1、現象概述
這個現象其實大部分都知道,迴圈依賴也是網上比較流傳Spring的一個問題。
比如現在有一個類為Class1,然後其有一個屬性為Class2,然後Class2這個類裡有一個屬性為Class1。當這兩個類都是單例的時候,就存在迴圈依賴的問題了。
那麼這種情況在Spring管理Bean的時候是如何解決的呢?
下面來描述
2、程式碼現象
Class1.java
@Component
public class Class1 {
@Autowired
private Class2 class2;
}
Class2.java
@Component public class Class2 { @Autowired private Class1 class1; }
用容器去獲取getBean
看我們的Class1,它的屬性class2有值,其Class2的屬性class1也有值,這就是迴圈依賴,下面我們來解釋Spring如何解決這個問題。
3、大概解釋
在看原始碼之前,我們先用白話文對其進行解釋。
首先我們Spring先去走Class1的生命週期,首先是用構造器建立Class1的物件,在建立結束以後,對Class1的屬性進行注入,在注入Class2的時候,實際上是去呼叫getBean(Class2),然後Class2在建立結束以後,又回去注入Class2中的class1屬性,那麼自然就會去呼叫getBean(Class1),此時去getBean(Class1)是能獲取到的,但注意次數獲取道德Class1屬性並未注入完成,那麼這樣Class2的class1屬性就注入完成,就回到了Class1注入class2的時候,這時Class1去getBean(Class2)就完成,注意此時Class2已經注入完成,那麼就將Class2注入到Class1的class2屬性中,至此,迴圈依賴就結束。
你可能有如下疑問:
Class1注入Class2的時候,是如何去getBean的?
Class2注入Class1的時候,為什麼getBean能獲取到Class1,具體程式碼在哪裡判斷的?為什麼獲取到Class1屬性並未注入完成?
下面原始碼解析中一一解釋。
4、原始碼解析
來到org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#doCreateBean中:
在進入這個方法之前,先展示方法棧:
好,現在進入方法程式碼:
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#doCreateBean
protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
throws BeanCreationException {
// Instantiate the bean.
BeanWrapper instanceWrapper = null;
if (mbd.isSingleton()) {
instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
}
if (instanceWrapper == null) {
/**
* 這裡實際上是去建立Bean了,
* 此類中屬性並未賦值,比如@Autowried
*
* */
instanceWrapper = createBeanInstance(beanName, mbd, args);
}
Object bean = instanceWrapper.getWrappedInstance();
Class<?> beanType = instanceWrapper.getWrappedClass();
if (beanType != NullBean.class) {
mbd.resolvedTargetType = beanType;
}
// Allow post-processors to modify the merged bean definition.
synchronized (mbd.postProcessingLock) {
if (!mbd.postProcessed) {
try {
applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
}
catch (Throwable ex) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Post-processing of merged bean definition failed", ex);
}
mbd.postProcessed = true;
}
}
// 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) {
if (logger.isDebugEnabled()) {
logger.debug("Eagerly caching bean '" + beanName +
"' to allow for resolving potential circular references");
}
/**
* 最主要是的將當前建立好的Bean放置到singletonFactories的Map中
* */
addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
}
// Initialize the bean instance.
Object exposedObject = bean;
try {
/* 填充Bean,填充其屬性的值 */
populateBean(beanName, mbd, instanceWrapper);
/**
* 去執行
* BeanPostProcessor的postProcessBeforeInitialization方法
* */
exposedObject = initializeBean(beanName, exposedObject, mbd);
}
catch (Throwable ex) {
if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) {
throw (BeanCreationException) ex;
}
else {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Initialization of bean failed", ex);
}
}
.......省略程式碼
return exposedObject;
}
此時我們的beanName為“class1”。
我們分段看:
// Instantiate the bean.
BeanWrapper instanceWrapper = null;
if (mbd.isSingleton()) {
instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
}
if (instanceWrapper == null) {
instanceWrapper = createBeanInstance(beanName, mbd, args);
}
Object bean = instanceWrapper.getWrappedInstance();
Class<?> beanType = instanceWrapper.getWrappedClass();
if (beanType != NullBean.class) {
mbd.resolvedTargetType = beanType;
}
這裡createBeanInstance是去建立類的例項,這個建立的例項當前是啥也沒有的,屬性並未填充。
// 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) {
if (logger.isDebugEnabled()) {
logger.debug("Eagerly caching bean '" + beanName +
"' to allow for resolving potential circular references");
}
/**
* 最主要是的將當前建立好的Bean放置到singletonFactories的Map中
* */
addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
}
addSingletonFactory這個方法最主要的就是將我們剛剛建立的例項加入到singletonFactories這個Map當中去,這個map在迴圈依賴裡面很重要,注意這個Map中的Class1是才建立好的,並沒有屬性注入。
// Initialize the bean instance.
Object exposedObject = bean;
try {
populateBean(beanName, mbd, instanceWrapper);
exposedObject = initializeBean(beanName, exposedObject, mbd);
}
catch (Throwable ex) {
if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) {
throw (BeanCreationException) ex;
}
else {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Initialization of bean failed", ex);
}
}
這裡面populateBean是完成屬性注入(換個叫法就是完成Bean填充),initializeBean是執行BeanPostProcessor的回撥,我們關心populateBean方法。
進入populateBena方法中。
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#populateBean
protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
if (bw == null) {
if (mbd.hasPropertyValues()) {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Cannot apply property values to null instance");
}
else {
// Skip property population phase for null instance.
return;
}
}
// Give any InstantiationAwareBeanPostProcessors the opportunity to modify the
// state of the bean before properties are set. This can be used, for example,
// to support styles of field injection.
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof InstantiationAwareBeanPostProcessor) {
InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
return;
}
}
}
}
PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null);
int resolvedAutowireMode = mbd.getResolvedAutowireMode();
if (resolvedAutowireMode == AUTOWIRE_BY_NAME || resolvedAutowireMode == AUTOWIRE_BY_TYPE) {
MutablePropertyValues newPvs = new MutablePropertyValues(pvs);
// Add property values based on autowire by name if applicable.
if (resolvedAutowireMode == AUTOWIRE_BY_NAME) {
autowireByName(beanName, mbd, bw, newPvs);
}
// Add property values based on autowire by type if applicable.
if (resolvedAutowireMode == AUTOWIRE_BY_TYPE) {
autowireByType(beanName, mbd, bw, newPvs);
}
pvs = newPvs;
}
/**
* 要不要處理
* */
boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();
/**
* 要不要深度檢查
*/
boolean needsDepCheck = (mbd.getDependencyCheck() != AbstractBeanDefinition.DEPENDENCY_CHECK_NONE);
if (hasInstAwareBpps || needsDepCheck) {
if (pvs == null) {
pvs = mbd.getPropertyValues();
}
/**
* 拿到所有的get/set方法
* */
PropertyDescriptor[] filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
if (hasInstAwareBpps) {
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof InstantiationAwareBeanPostProcessor) {
/**
* 重點看這個PostProcess:org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor
* 這個是去處理自動注入的.
* */
InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
pvs = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
if (pvs == null) {
return;
}
}
}
}
if (needsDepCheck) {
checkDependencies(beanName, mbd, filteredPds, pvs);
}
}
if (pvs != null) {
applyPropertyValues(beanName, mbd, bw, pvs);
}
分段看:
if (bw == null) {
if (mbd.hasPropertyValues()) {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Cannot apply property values to null instance");
}
else {
// Skip property population phase for null instance.
return;
}
}
判空處理,這個沒什麼好解釋。
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof InstantiationAwareBeanPostProcessor) {
InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
return;
}
}
}
}
InstantiationAwareBeanPostProcessor的方法postProcessAfterInstantiation,該方法的返回值是boolean,如果返回true,則什麼都不幹,如果返回false,那麼此類則不會進行自動裝配(屬性填充),這裡就是可以讓我們通過postprocessor的方式控制某些bean不用屬性填充。這裡很明顯如果我們沒做特殊處理,這裡最裡面的if的return是不會被執行到的。
int resolvedAutowireMode = mbd.getResolvedAutowireMode();
if (resolvedAutowireMode == AUTOWIRE_BY_NAME || resolvedAutowireMode == AUTOWIRE_BY_TYPE) {
MutablePropertyValues newPvs = new MutablePropertyValues(pvs);
// Add property values based on autowire by name if applicable.
if (resolvedAutowireMode == AUTOWIRE_BY_NAME) {
autowireByName(beanName, mbd, bw, newPvs);
}
// Add property values based on autowire by type if applicable.
if (resolvedAutowireMode == AUTOWIRE_BY_TYPE) {
autowireByType(beanName, mbd, bw, newPvs);
}
pvs = newPvs;
}
resolvedAutowireMode:自動注入模型,預設為AUTOWIRE_CONSTRUCTOR,所以這裡不會進if,如果該BeanDefinition的注入模型是這兩種的,那麼則分別的可以嘗試byType方式,byName方式。
/**
* 要不要處理
* */
boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();
/**
* 要不要深度檢查
*/
boolean needsDepCheck = (mbd.getDependencyCheck() != AbstractBeanDefinition.DEPENDENCY_CHECK_NONE);
這兩個屬性註釋上有,很明顯都為true。
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof InstantiationAwareBeanPostProcessor) {
/**
* 重點看這個PostProcess:org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor
* 這個是去處理自動注入的.
* */
InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
pvs = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
if (pvs == null) {
return;
}
}
}
屬性注入是使用BeanPostProcessor來完成的。
這裡是使用BeanPostProcessor的子類InstantiationAwareBeanPostProcessor來完成屬性注入,這裡面很多InstantiationAwareBeanPostProcessor,我們主要關心AutowiredAnnotationBeanPostProcessor的postProcessPropertyValues方法,我們進入AutowiredAnnotationBeanPostProcessor的postProcessPropertyValues方法來看。
org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor#postProcessPropertyValues
@Override
public PropertyValues postProcessPropertyValues(
PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeanCreationException {
/**
* 拿到需要注入的欄位,這個方法不需要去深究
* */
InjectionMetadata metadata = findAutowiringMetadata(beanName, bean.getClass(), pvs);
try {
metadata.inject(bean, beanName, pvs);
}
catch (BeanCreationException ex) {
throw ex;
}
catch (Throwable ex) {
throw new BeanCreationException(beanName, "Injection of autowired dependencies failed", ex);
}
return pvs;
}
分段看:
InjectionMetadata metadata = findAutowiringMetadata(beanName, bean.getClass(), pvs);
這個是去獲取到當前類中需要注入的屬性,注意此時beanName為前面說到的class1,bean.getClass()為Class1。
我們來斷點看看當前的metadata中是否包含了我們Class1中需要注入的class2屬性。
那麼我們進入metadata.inject方法。
org.springframework.beans.factory.annotation.InjectionMetadata#inject
public void inject(Object target, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {
Collection<InjectedElement> checkedElements = this.checkedElements;
Collection<InjectedElement> elementsToIterate =
(checkedElements != null ? checkedElements : this.injectedElements);
if (!elementsToIterate.isEmpty()) {
for (InjectedElement element : elementsToIterate) {
if (logger.isDebugEnabled()) {
logger.debug("Processing injected element of bean '" + beanName + "': " + element);
}
/**
* 對屬性進行注入操作,當前的element是需要被注入的欄位,target是原類的例項物件,beanName是bean的名稱,是target的類名稱
* 注意,這個Element為:AutowiredFieldElement
* */
element.inject(target, beanName, pvs);
}
}
}
將剛才找到的所有需要注入的屬性遍歷給注入。
我們進入element.inject方法,注意此時的target為Class1,beanName為class1。
org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.AutowiredFieldElement#inject
@Override
protected void inject(Object bean, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {
Field field = (Field) this.member;
Object value;
if (this.cached) {
value = resolvedCachedArgument(beanName, this.cachedFieldValue);
}
else {
/**
* 可以理解為欄位的描述
*/
DependencyDescriptor desc = new DependencyDescriptor(field, this.required);
desc.setContainingClass(bean.getClass());
Set<String> autowiredBeanNames = new LinkedHashSet<>(1);
Assert.state(beanFactory != null, "No BeanFactory available");
TypeConverter typeConverter = beanFactory.getTypeConverter();
try {
value = beanFactory.resolveDependency(desc, beanName, autowiredBeanNames, typeConverter);
}
catch (BeansException ex) {
throw new UnsatisfiedDependencyException(null, beanName, new InjectionPoint(field), ex);
}
synchronized (this) {
if (!this.cached) {
if (value != null || this.required) {
this.cachedFieldValue = desc;
registerDependentBeans(beanName, autowiredBeanNames);
if (autowiredBeanNames.size() == 1) {
String autowiredBeanName = autowiredBeanNames.iterator().next();
if (beanFactory.containsBean(autowiredBeanName) &&
beanFactory.isTypeMatch(autowiredBeanName, field.getType())) {
this.cachedFieldValue = new ShortcutDependencyDescriptor(
desc, autowiredBeanName, field.getType());
}
}
}
else {
this.cachedFieldValue = null;
}
this.cached = true;
}
}
}
if (value != null) {
ReflectionUtils.makeAccessible(field);
field.set(bean, value);
}
}
分段看:
Object value;
這個value就是用來存放例項化出來以後的Class2物件。
value = beanFactory.resolveDependency(desc, beanName, autowiredBeanNames, typeConverter);
此處就是去getBean(Class2),然後再將拿到的value設定到Class1的class2屬性當中去。
if (value != null) {
ReflectionUtils.makeAccessible(field);
field.set(bean, value);
}
設定到Class1的class2屬性中去。
我們現在來看beanFactory.resolveDependency方法。
org.springframework.beans.factory.support.DefaultListableBeanFactory#resolveDependency
@Override
@Nullable
public Object resolveDependency(DependencyDescriptor descriptor, @Nullable String requestingBeanName,
@Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException {
descriptor.initParameterNameDiscovery(getParameterNameDiscoverer());
if (Optional.class == descriptor.getDependencyType()) {
return createOptionalDependency(descriptor, requestingBeanName);
}
else if (ObjectFactory.class == descriptor.getDependencyType() ||
ObjectProvider.class == descriptor.getDependencyType()) {
return new DependencyObjectProvider(descriptor, requestingBeanName);
}
else if (javaxInjectProviderClass == descriptor.getDependencyType()) {
return new Jsr330ProviderFactory().createDependencyProvider(descriptor, requestingBeanName);
}
else {
Object result = getAutowireCandidateResolver().getLazyResolutionProxyIfNecessary(
descriptor, requestingBeanName);
if (result == null) {
/**
* 例項化
* */
result = doResolveDependency(descriptor, requestingBeanName, autowiredBeanNames, typeConverter);
}
return result;
}
}
如果我們的欄位型別是這些指定的某個class型別,那麼則特殊處理,如果都不是,則else裡面進行處理。
我們這裡直不是特殊的型別,直接進入doResolveDependency。
org.springframework.beans.factory.support.DefaultListableBeanFactory#doResolveDependency
@Nullable
public Object doResolveDependency(DependencyDescriptor descriptor, @Nullable String beanName,
@Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException {
.....省略
if (instanceCandidate instanceof Class) {
/**
* 去使用beanFactory.getBean去建立這個屬性的Bean
* */
instanceCandidate = descriptor.resolveCandidate(autowiredBeanName, type, this);
}
.....省略
return result;
}
finally {
ConstructorResolver.setCurrentInjectionPoint(previousInjectionPoint);
}
}
上下的程式碼都根本次的迴圈依賴沒關係,我們重點看這個if裡面的。
注意此時的autowiredBeanName為:class2,此時的type為:com.dh.pojo.Class2,此時的this為:BeanFactory。
現在進入descriptor.resolveCandidate方法:
org.springframework.beans.factory.config.DependencyDescriptor#resolveCandidate
public Object resolveCandidate(String beanName, Class<?> requiredType, BeanFactory beanFactory)
throws BeansException {
return beanFactory.getBean(beanName);
}
這裡可以看到,其實是去beanFactory中呼叫getBean方法。
到達org.springframework.beans.factory.support.AbstractBeanFactory#doGetBean方法中。
我們這裡快速的過去,不去細究這個例如建立的Class2:
到達org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#doCreateBean方法中:
protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
throws BeanCreationException {
。。。。省略
// Initialize the bean instance.
Object exposedObject = bean;
try {
/* 填充Bean,填充其屬性的值 */
populateBean(beanName, mbd, instanceWrapper);
/**
* 去執行
* BeanPostProcessor的postProcessBeforeInitialization方法
* */
exposedObject = initializeBean(beanName, exposedObject, mbd);
}
catch (Throwable ex) {
if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) {
throw (BeanCreationException) ex;
}
else {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Initialization of bean failed", ex);
}
}
。。。。省略
return exposedObject;
}
注意現在這個時候,beanName為class2。
進入populateBean方法後我們再次進入org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor#postProcessPropertyValues方法中。
org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor#postProcessPropertyValues
public PropertyValues postProcessPropertyValues(
PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeanCreationException {
/**
* 拿到需要注入的欄位,這個方法不需要去深究
* */
InjectionMetadata metadata = findAutowiringMetadata(beanName, bean.getClass(), pvs);
try {
metadata.inject(bean, beanName, pvs);
}
catch (BeanCreationException ex) {
throw ex;
}
catch (Throwable ex) {
throw new BeanCreationException(beanName, "Injection of autowired dependencies failed", ex);
}
return pvs;
}
再次進入metadata.inject方法,org.springframework.beans.factory.annotation.InjectionMetadata#inject
org.springframework.beans.factory.annotation.InjectionMetadata#inject
public void inject(Object target, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {
Collection<InjectedElement> checkedElements = this.checkedElements;
Collection<InjectedElement> elementsToIterate =
(checkedElements != null ? checkedElements : this.injectedElements);
if (!elementsToIterate.isEmpty()) {
for (InjectedElement element : elementsToIterate) {
if (logger.isDebugEnabled()) {
logger.debug("Processing injected element of bean '" + beanName + "': " + element);
}
/**
* 對屬性進行注入操作,當前的element是需要被注入的欄位,target是原類的例項物件,beanName是bean的名稱,是target的類名稱
* 注意,這個Element為:AutowiredFieldElement
* */
element.inject(target, beanName, pvs);
}
}
}
注意此時的target為Class2,beanName為class2,此時是需要去注入Class2中的class1屬性的。
那麼此時我們跳躍一下程式碼,中間的都不是關鍵,到達org.springframework.beans.factory.support.AbstractBeanFactory#doGetBean中來。
protected <T> T doGetBean(
String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly)
throws BeansException {
/* 此處需要處理FactoryBean的情況,如果是FactoryBean的話,此處的BeanName為&xxxx,此處需要將&去掉 */
String beanName = transformedBeanName(name);
Object bean;
/*
* 去當前容器中獲取例項化好的Bean,如果bean不為空,則直接返回了,如果為空,則需要去例項化,進入else
* */
// Eagerly check singleton cache for manually registered singletons.
Object sharedInstance = getSingleton(beanName);
if (sharedInstance != null && args == null) {
if (logger.isDebugEnabled()) {
if (isSingletonCurrentlyInCreation(beanName)) {
logger.debug("Returning eagerly cached instance of singleton bean '" + beanName +
"' that is not fully initialized yet - a consequence of a circular reference");
}
else {
logger.debug("Returning cached instance of singleton bean '" + beanName + "'");
}
}
bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
}
....else省略
return (T) bean;
}
注意此時的beanName為“class1”,然後注意Object sharedInstance = getSingleton(beanName);中得到的sharedInstance不為空,這裡很重要,是解決迴圈依賴最重要的位置。你如果細心可以發現,在第一次Class1進入doGetBean的時候,這裡的getSingleton結果為空,第二次Class2進入doGetBean的時候,這裡的getSingleton結果也是空,第三次Class1進入doGetBean的時候,getSingleton結果不是空了。
那麼這裡可以看到如果sharedInstance不為空的話,就不會進入else,else裡面是進行建立bean的程式碼,if裡面的話,就會在後面直接return這個bean。
那麼這裡我們大概就知道了,來理一下,
1、第一次Class1建立的時候,getSingleton為空那麼建立物件。
2、Class1注入Class2,那麼Class2這裡getSingleton為空,那麼則建立物件。
3、Class2注入Class1的時候,這裡Class1的getSingleton不為空,那麼Class2就成功的注入得到了Class1。
4、當Class2注入完成Class1以後,就回到了Class1注入Class2的位置,這個時候Class1已經成功拿到了Class2,那麼就將其注入到Class1自己的屬性裡面去。
至此迴圈依賴就解決了。
但是需要注意,當3步的時候,Class1的getSingleton得到的物件中,其屬性並未注入完成。
那麼就代表這個時候拿到的Class1就是一個未填充完成的物件。
但是這種方式是可以解決迴圈依賴的問題的。
那麼這裡我們有一些問題還沒有解決:
1、getSingleton為什麼能拿到Class1
2、有人可能聽說過,是快取,說白了這個快取就是一個Map,存放臨時的Class1,那麼這個Map是哪個呢,臨時的Class1是何時存入Map中的呢?
首先我們來看getSingleton方法怎麼獲取到Class1的:
org.springframework.beans.factory.support.DefaultSingletonBeanRegistry#getSingleton(java.lang.String)
@Override
@Nullable
public Object getSingleton(String beanName) {
return getSingleton(beanName, true);
}
再次進入getSingleton方法。
org.springframework.beans.factory.support.DefaultSingletonBeanRegistry#getSingleton(java.lang.String, boolean)
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);
if (singletonFactory != null) {
singletonObject = singletonFactory.getObject();
this.earlySingletonObjects.put(beanName, singletonObject);
this.singletonFactories.remove(beanName);
}
}
}
}
return singletonObject;
}
首先this.singletonObjects.get(beanName)結果肯定為空,因為這個singletonObjects集合中存放的是已經走過完整生命週期的Bean,很明顯我們這裡的Class1並沒有。
那麼下面的這個if會進入,singletonObjects為空這個true我們知道,我們來看看isSingletonCurrentlyInCreation(beanName),注意此時的beanName為class1。
public boolean isSingletonCurrentlyInCreation(String beanName) {
return this.singletonsCurrentlyInCreation.contains(beanName);
}
注意此時的singletonsCurrentlyInCreation裡面的元素為:
這個集合代表著,當前正在建立的物件,此時我們的Class1和Class2在這裡面。
那麼自然這個if就能進去了。
然後注意看if裡面singletonObject = this.earlySingletonObjects.get(beanName);
這個時候獲取的仍然是空的。但是下一行中this.singletonFactories.get(beanName)裡面就不是空了
這裡可以看得到,成功的拿出了Class1這個物件,且裡面的class2屬性為空的。
那麼我們這裡就看明白整體了。我這裡再描述一遍。
1、建立Class1物件,並將其beanName放置到singletonsCurrentlyInCreation集合中、singletonFactories集合中。
2、注入Class1中的class2,這時需要去建立Class2,並將其Class2的beanName放置到singletonsCurrentlyInCreation集合中、singletonFactories集合中。
3、再對Class2進行注入class1屬性,這時getSingleton方法中就能拿到Class1這個物件,那麼getSingleton中首先判斷當前Class1是否在singletonsCurrentlyInCreation集合中,如果在,那麼就從singletonFactories集合中將其取出。
那麼我們最後再來看一個東西,看Spring在何時將beanName存放至singletonsCurrentlyInCreation集合中,何時將建立好的物件存放至singletonFactories中。
進入到:org.springframework.beans.factory.support.DefaultSingletonBeanRegistry#getSingleton(java.lang.String, org.springframework.beans.factory.ObjectFactory<?>)
org.springframework.beans.factory.support.DefaultSingletonBeanRegistry#getSingleton(java.lang.String, org.springframework.beans.factory.ObjectFactory<?>)
注意看這個方法,beforeSingletonCreation,進入這個方法。
org.springframework.beans.factory.support.DefaultSingletonBeanRegistry#beforeSingletonCreation
protected void beforeSingletonCreation(String beanName) {
if (!this.inCreationCheckExclusions.contains(beanName) && !this.singletonsCurrentlyInCreation.add(beanName)) {
throw new BeanCurrentlyInCreationException(beanName);
}
}
注意看這裡將當前的beanName存放至singletonsCurrentlyInCreation集合當中去,這裡我們找到了在哪裡存放到singletonsCurrentlyInCreation集合中去的。
注意這個getSingleton方法中會去呼叫doCreateBean方法。
然後我們再來找何時存放至singletonFactories集合中的,注意這個Map的value是一個物件,那麼代表是在我們Bean建立完以後才存放至這個集合中的。
進入到org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#doCreateBean方法中
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#doCreateBean
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);
}
}
}
這裡的!this.singletonObjects.containsKey(beanName)其實就是當前Bean如果沒有走完生命週期的話,就會進入這個IF,因為singletonObjects集合中是存放已經走完生命週期的。
然後下面就是將當前的Bean加入到singletonFactories集合中。
至此,我們迴圈依賴已經結束,如有不明白的地方,可翻閱隨筆中內容,如有其他疑問可留言或評論。