全文都是Spring解決循環依賴幹貨,建議關注收藏,然後打開源碼結合源碼看,不然會頭暈.
1 什麼是循環依賴?
在Spring中的循環依賴,簡單的來說加入我們現在有A、B兩個個對象,示例如下:
@Bean
public class A {
@Autowire
private B b;
}
@Bean
public class B {
@Autowire
private A a;
}
假如Spring沒有幫我們解決循環依賴,看一下會出現什麼情況?
建立對象A-->處理A的依賴B-->建立對象B-->處理B的對象A-->建立對象A-->處理A的依賴B......
從上面的示例可以看出對象的依賴注入就進入到了死循環,這樣是不是很好的了解了什麼是循環依賴。
2 Spring如何解決循環依賴的?
對于循環依賴,其實Spring早就為我們考慮到了并且解決了這個問題,這就是Java中Spring的強大之處了。
其實Spring解決循環依賴的方案就是:三級緩存機制
1、一級緩存【singletonObiects】:用來儲存執行個體化、注入、初始化完成的bean執行個體
2、二級緩存【earlySingletonObject】:用來儲存執行個體化完成的bean執行個體
3、三級緩存【singletonFactories】:用來儲存bean建立工廠,便于後面擴充有機會建立代理對象。
先用一張邏輯圖來了解一下Spring的三級緩存:
我們來了解一下Spring的三級緩存解決循環依賴:
1、建立A對象先去一級緩存中擷取執行個體A,擷取不到,然後就建立A并把A放入到三級緩存中。
2、建立A依賴注入了B,又去建立B,同樣去一級緩存中擷取不到B,于是就建立B并放入三級緩存中。
2、這時B依賴A,從三級緩存中擷取到了A,并把A放入二級緩存中;這時B就能初始化成功了,然後把B放入到一級緩存中。
3、這時因在二級緩存中能擷取到A,是以A能初始化成功,并把A放入到一級緩存中。
至此Spring的循環依賴就解決完了。
3 Spring解決循環依賴源碼分析
1、首先啟動Spring容器,建立A執行個體時,來到 AbstractBeanFactory.doGetBean()方法,走一級緩存中拿A對象,當然這裡時肯定沒有拿到對象的
protected <T> T doGetBean(String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly) throws BeansException {
String beanName = this.transformedBeanName(name);
//先去一級緩存拿對象
Object sharedInstance = this.getSingleton(beanName);
Object beanInstance;
//沒拿到
if (sharedInstance != null && args == null) {
if (this.logger.isTraceEnabled()) {
if (this.isSingletonCurrentlyInCreation(beanName)) {
this.logger.trace("Returning eagerly cached instance of singleton bean '" + beanName + "' that is not fully initialized yet - a consequence of a circular reference");
} else {
this.logger.trace("Returning cached instance of singleton bean '" + beanName + "'");
}
}
beanInstance = this.getObjectForBeanInstance(sharedInstance, name, beanName, (RootBeanDefinition)null);
} ....//這裡省略了else代碼,後續我們分析的時候貼出來
2、直接來到建立擷取單例執行個體的位置
....//有代碼省略
if (mbd.isSingleton()) {
//進入這個方法
sharedInstance = this.getSingleton(beanName, () -> {
try {
//mbd這個參數時一個方法的lamda表達式,下面會調用這裡
return this.createBean(beanName, mbd, args);
} catch (BeansException var5) {
this.destroySingleton(beanName);
throw var5;
}
});
beanInstance = this.getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}
....//有代碼省略
3、到了 DefaultSingletonBeanRegistry.getSingleton() 方法
public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
Assert.notNull(beanName, "Bean name must not be null");
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!)");
}
if (this.logger.isDebugEnabled()) {
this.logger.debug("Creating shared instance of singleton bean '" + beanName + "'");
}
this.beforeSingletonCreation(beanName);
boolean newSingleton = false;
boolean recordSuppressedExceptions = this.suppressedExceptions == null;
if (recordSuppressedExceptions) {
this.suppressedExceptions = new LinkedHashSet();
}
try {
//這裡就調用了上面說到的lamda表達式方法
singletonObject = singletonFactory.getObject();
newSingleton = true;
} catch (IllegalStateException var16) {
singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null) {
throw var16;
}
} catch (BeanCreationException var17) {
BeanCreationException ex = var17;
if (recordSuppressedExceptions) {
Iterator var8 = this.suppressedExceptions.iterator();
while(var8.hasNext()) {
Exception suppressedException = (Exception)var8.next();
ex.addRelatedCause(suppressedException);
}
}
throw ex;
} finally {
if (recordSuppressedExceptions) {
this.suppressedExceptions = null;
}
this.afterSingletonCreation(beanName);
}
if (newSingleton) {
this.addSingleton(beanName, singletonObject);
}
}
return singletonObject;
}
}
4、來到了 AbstractAutowireCapableBeanFactory.createBean() 方法。
public <T> T createBean(Class<T> beanClass) throws BeansException {
RootBeanDefinition bd = new RootBeanDefinition(beanClass);
bd.setScope("prototype");
bd.allowCaching = ClassUtils.isCacheSafe(beanClass, this.getBeanClassLoader());
//跳進去createBean()
return this.createBean(beanClass.getName(), bd, (Object[])null);
}
protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) throws BeanCreationException {
if (this.logger.isTraceEnabled()) {
this.logger.trace("Creating instance of bean '" + beanName + "'");
}
RootBeanDefinition mbdToUse = mbd;
Class<?> resolvedClass = this.resolveBeanClass(mbd, beanName, new Class[0]);
if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
mbdToUse = new RootBeanDefinition(mbd);
mbdToUse.setBeanClass(resolvedClass);
}
try {
mbdToUse.prepareMethodOverrides();
} catch (BeanDefinitionValidationException var9) {
throw new BeanDefinitionStoreException(mbdToUse.getResourceDescription(), beanName, "Validation of method overrides failed", var9);
}
Object beanInstance;
try {
beanInstance = this.resolveBeforeInstantiation(beanName, mbdToUse);
if (beanInstance != null) {
return beanInstance;
}
} catch (Throwable var10) {
throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName, "BeanPostProcessor before instantiation of bean failed", var10);
}
try {
//進入到這裡,建立執行個體對象
beanInstance = this.doCreateBean(beanName, mbdToUse, args);
if (this.logger.isTraceEnabled()) {
this.logger.trace("Finished creating instance of bean '" + beanName + "'");
}
return beanInstance;
} catch (ImplicitlyAppearedSingletonException | BeanCreationException var7) {
throw var7;
} catch (Throwable var8) {
throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName, "Unexpected exception during bean creation", var8);
}
}
5、還是AbstractAutowireCapableBeanFactory.doCreateBean()方法,這裡先建立并獲得執行個體對象
protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) throws BeanCreationException {
BeanWrapper instanceWrapper = null;
if (mbd.isSingleton()) {
instanceWrapper = (BeanWrapper)this.factoryBeanInstanceCache.remove(beanName);
}
if (instanceWrapper == null) {
//建立執行個體
instanceWrapper = this.createBeanInstance(beanName, mbd, args);
}
//獲得執行個體
Object bean = instanceWrapper.getWrappedInstance();
Class<?> beanType = instanceWrapper.getWrappedClass();
if (beanType != NullBean.class) {
mbd.resolvedTargetType = beanType;
}
.....//源碼省略
6、同樣是AbstractAutowireCapableBeanFactory.doCreateBean()方法,然後來到了這裡,放入bean到三級緩存的代碼部分
....//省略源碼
boolean earlySingletonExposure = mbd.isSingleton() && this.allowCircularReferences && this.isSingletonCurrentlyInCreation(beanName);
if (earlySingletonExposure) {
if (this.logger.isTraceEnabled()) {
this.logger.trace("Eagerly caching bean '" + beanName + "' to allow for resolving potential circular references");
}
//放入三級緩存
this.addSingletonFactory(beanName, () -> {
return this.getEarlyBeanReference(beanName, mbd, bean);
});
}
Object exposedObject = bean;
......//省略源碼
7、繼續AbstractAutowireCapableBeanFactory.addSingletonFactory(....)方法,首先判斷一級緩存有無對應執行個體(此時沒有),接着将傳入的 () -> getEarlyBeanReference(beanName, mbd, bean) 放到三級緩存 singletonFactories 中,這時候三級緩存就有對象了,此時的對象隻是一個 帶有方法
() -> getEarlyBeanReference(beanName, mbd, bean) 的 objectFactory對象
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);
}
}
}
8、放入三級緩存後,回到AbstractAutowireCapableBeanFactory.doCreateBean()方法,這裡就開始依賴注入了
....//代碼省略
Object exposedObject = bean;
try {
//依賴注入
this.populateBean(beanName, mbd, instanceWrapper);
exposedObject = this.initializeBean(beanName, exposedObject, mbd);
} catch (Throwable var18) {
if (var18 instanceof BeanCreationException && beanName.equals(((BeanCreationException)var18).getBeanName())) {
throw (BeanCreationException)var18;
}
throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Initialization of bean failed", var18);
}
...//代碼省略
9、然後對屬性B注入,又回到AbstractBeanFactory.doGetBean()方法建立A的步驟去建立對象B,也是走到依賴注入這裡,這時候需要對B的屬性A進行注入,是以又來到建立A的階段 AbstractBeanFactory.doCreateBean()方法,不過此時的 三級緩存 singletonFactories 已經A了。
protected <T> T doGetBean(String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly) throws BeansException {
String beanName = this.transformedBeanName(name);
//回到了這裡,這次是走三級緩存中拿到了A
Object sharedInstance = this.getSingleton(beanName);
Object beanInstance;
if (sharedInstance != null && args == null) {
if (this.logger.isTraceEnabled()) {
if (this.isSingletonCurrentlyInCreation(beanName)) {
this.logger.trace("Returning eagerly cached instance of singleton bean '" + beanName + "' that is not fully initialized yet - a consequence of a circular reference");
} else {
this.logger.trace("Returning cached instance of singleton bean '" + beanName + "'");
}
}
beanInstance = this.getObjectForBeanInstance(sharedInstance, name, beanName, (RootBeanDefinition)null);
...//代碼省略
10、進入AbstractBeanFactory.getSingleton()方法,裡面就是處理的去三級緩存拿資料的邏輯。
@Nullable
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
//走一級緩存拿A
Object singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null && this.isSingletonCurrentlyInCreation(beanName)) {
//二級緩存中拿A
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
ObjectFactory<?> singletonFactory = (ObjectFactory)this.singletonFactories.get(beanName);
if (singletonFactory != null) {
//執行前面提到過的lamda表達式方法
singletonObject = singletonFactory.getObject();
//放入耳機緩存
this.earlySingletonObjects.put(beanName, singletonObject);
//移除一級緩存
this.singletonFactories.remove(beanName);
}
}
}
}
}
}
return singletonObject;
}
11、繼續來到AbstractBeanFactory.getSingleton()方法點進去,B拿到A進行依賴注入,繼續 AbstractAutowireCapableBeanFactory.createBean() 方法,再進入到DefaultSingletonBeanRegistry.getSingleton()方法,此時B一級拿到了。
public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
Assert.notNull(beanName, "Bean name must not be null");
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!)");
}
if (this.logger.isDebugEnabled()) {
this.logger.debug("Creating shared instance of singleton bean '" + beanName + "'");
}
this.beforeSingletonCreation(beanName);
boolean newSingleton = false;
boolean recordSuppressedExceptions = this.suppressedExceptions == null;
if (recordSuppressedExceptions) {
this.suppressedExceptions = new LinkedHashSet();
}
try {
singletonObject = singletonFactory.getObject();
//這裡就能看到拿到了B對象的執行個體
newSingleton = true;
} catch (IllegalStateException var16) {
singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null) {
throw var16;
}
} catch (BeanCreationException var17) {
BeanCreationException ex = var17;
if (recordSuppressedExceptions) {
Iterator var8 = this.suppressedExceptions.iterator();
while(var8.hasNext()) {
Exception suppressedException = (Exception)var8.next();
ex.addRelatedCause(suppressedException);
}
}
throw ex;
} finally {
if (recordSuppressedExceptions) {
this.suppressedExceptions = null;
}
this.afterSingletonCreation(beanName);
}
if (newSingleton) {
this.addSingleton(beanName, singletonObject);
}
}
return singletonObject;
}
}
12、繼續 AbstractAutowireCapableBeanFactory.createBean() 方法,将B放入一級緩存,同時移除二級緩存和三級緩存中的B,此時B可建立完成,最後傳回B給A,A也就完成注入了,最後把A放入一級緩存,移除二級緩存和三級緩存中的A。至此A也建立好了。
....//代碼省略
if (recordSuppressedExceptions) {
this.suppressedExceptions = null;
}
this.afterSingletonCreation(beanName);
}
if (newSingleton) {
//B放入一級緩存
this.addSingleton(beanName, singletonObject);
}
}
return singletonObject;
...//源碼省略
3 Spring為什麼要用三級緩存解決循環依賴?
這裡簡短的提一下,當A類使用注解@Transactional時,如果不用三級緩存就解決不了,具體的大家下來再了解一下,這就是為什麼Spring用三級緩存解決循環依賴而不是二級緩存。