免费视频淫片aa毛片_日韩高清在线亚洲专区vr_日韩大片免费观看视频播放_亚洲欧美国产精品完整版

打開APP
userphoto
未登錄

開通VIP,暢享免費(fèi)電子書等14項(xiàng)超值服

開通VIP
Spring高頻面試題:如何解決循環(huán)依賴問題!

你知道的越多,不知道的就越多,業(yè)余的像一棵小草!

你來,我們一起精進(jìn)!你不來,我和你的競爭對手一起精進(jìn)!

編輯:業(yè)余草

juejin.cn/post/6895753832815394824

推薦:https://www.xttblog.com/?p=5123

Spring高頻面試題:如何解決循環(huán)依賴問題!

循環(huán)依賴問題全景圖

什么是循環(huán)依賴問題?

?

類與類之間的依賴關(guān)系形成了閉環(huán),就會導(dǎo)致循環(huán)依賴問題的產(chǎn)生。

?
?

比如下圖中A類依賴了B類,B類依賴了C類,而最后C類又依賴了A類,這樣就形成了循環(huán)依賴問題。

?

循環(huán)依賴問題案例分析

演示代碼:

public class ClassA {
 private ClassB classB;

 public ClassB getClassB() {
  return classB;
 }

 public void setClassB(ClassB classB) {
  this.classB = classB;
 }
}
public class ClassB {
 private ClassA classA;

 public ClassA getClassA() {
  return classA;
 }

 public void setClassA(ClassA classA) {
  this.classA = classA;
 }
}

配置文件:

<?xml version='1.0' encoding='UTF-8'?>
<beans xmlns='http://www.springframework.org/schema/beans'
 xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'
 xsi:schemaLocation='http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd'
>


 <bean id='classA' class='ioc.cd.ClassA'>
  <property name='classB' ref='classB'></property>
 </bean>
 <bean id='classB' class='ioc.cd.ClassB'>
  <property name='classA' ref='classA'></property>
 </bean>
</beans>

測試代碼:

@Test
public void test() throws Exception {
 // 創(chuàng)建IoC容器,并進(jìn)行初始化
 String resource = 'spring/spring-ioc-circular-dependency.xml';
 ApplicationContext context = new ClassPathXmlApplicationContext(resource);
 // 獲取ClassA的實(shí)例(此時會發(fā)生循環(huán)依賴)
 ClassA classA = (ClassA) context.getBean(ClassA.class);
}

通過Spring IOC流程的源碼分析循環(huán)依賴問題:

以上案例有幾種循環(huán)依賴問題?

循環(huán)依賴問題在Spring中主要有三種情況:

  • 通過構(gòu)造方法進(jìn)行依賴注入時產(chǎn)生的循環(huán)依賴問題。
  • 通過setter方法進(jìn)行依賴注入且是在多例(原型)模式下產(chǎn)生的循環(huán)依賴問題。
  • 通過setter方法進(jìn)行依賴注入且是在單例模式下產(chǎn)生的循環(huán)依賴問題。
?

注意:在Spring中,只有【第三種方式】的循環(huán)依賴問題被解決了,其他兩種方式在遇到循環(huán)依賴問題時都會產(chǎn)生異常。

?

其實(shí)也很好解釋:

  • 第一種構(gòu)造方法注入的情況下,在new對象的時候就會堵塞住了,其實(shí)也就是”先有雞還是先有蛋“的歷史難題。
  • 第二種setter方法&&多例的情況下,每一次getBean()時,都會產(chǎn)生一個新的Bean,如此反復(fù)下去就會有無窮無盡的Bean產(chǎn)生了,最終就會導(dǎo)致OOM問題的出現(xiàn)。

如何解決循環(huán)依賴問題?

那Spring到底是如何解決的setter方法依賴注入引起的循環(huán)依賴問題呢?請看下圖(其實(shí)主要是通過兩個緩存來解決的):

Spring三大緩存介紹

Spring中有三個緩存,用于存儲單例的Bean實(shí)例,這三個緩存是彼此互斥的,不會針對同一個Bean的實(shí)例同時存儲。

?

如果調(diào)用getBean,則需要從三個緩存中依次獲取指定的Bean實(shí)例。讀取順序依次是一級緩存-->二級緩存-->三級緩存

?

一級緩存:Map<String, Object> singletonObjects

第一級緩存的作用?

  • 用于存儲單例模式下創(chuàng)建的Bean實(shí)例(已經(jīng)創(chuàng)建完畢)。
  • 該緩存是對外使用的,指的就是使用Spring框架的程序員。

存儲什么數(shù)據(jù)?

  • K:bean的名稱
  • V:bean的實(shí)例對象(有代理對象則指的是代理對象,已經(jīng)創(chuàng)建完畢)

第二級緩存:Map<String, Object> earlySingletonObjects

第二級緩存的作用?

  • 用于存儲單例模式下創(chuàng)建的Bean實(shí)例(該Bean被提前暴露的引用,該Bean還在創(chuàng)建中)。
  • 該緩存是對內(nèi)使用的,指的就是Spring框架內(nèi)部邏輯使用該緩存。
  • 為了解決第一個classA引用最終如何替換為代理對象的問題(如果有代理對象)請爬樓參考演示案例

存儲什么數(shù)據(jù)?

  • K:bean的名稱
  • V:bean的實(shí)例對象(有代理對象則指的是代理對象,該Bean還在創(chuàng)建中)

第三級緩存:Map<String, ObjectFactory<?>> singletonFactories

第三級緩存的作用?

通過ObjectFactory對象來存儲單例模式下提前暴露的Bean實(shí)例的引用(正在創(chuàng)建中)。該緩存是對內(nèi)使用的,指的就是Spring框架內(nèi)部邏輯使用該緩存。此緩存是解決循環(huán)依賴最大的功臣

存儲什么數(shù)據(jù)?

  • K:bean的名稱
  • V:ObjectFactory,該對象持有提前暴露的bean的引用

?

為什么第三級緩存要使用ObjectFactory?需要提前產(chǎn)生代理對象。

?

?

什么時候?qū)ean的引用提前暴露給第三級緩存的ObjectFactory持有?時機(jī)就是在第一步實(shí)例化之后,第二步依賴注入之前,完成此操作。

?

總結(jié)

以上就是Spring解決循環(huán)依賴的關(guān)鍵點(diǎn)!總結(jié)來說,就是要搞清楚以下幾點(diǎn):

  • 搞清楚Spring三級緩存的作用?
  • 搞清楚第三級緩存中ObjectFactory的作用?
  • 搞清楚為什么需要第二級緩存?
  • 搞清楚什么時候使用三級緩存(添加和查詢操作)?
  • 搞清楚什么時候使用二級緩存(添加和查詢操作)?
  • 當(dāng)目標(biāo)對象產(chǎn)生代理對象時,Spring容器中(第一級緩存)到底存儲的是誰?

本站僅提供存儲服務(wù),所有內(nèi)容均由用戶發(fā)布,如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點(diǎn)擊舉報(bào)。
打開APP,閱讀全文并永久保存 查看更多類似文章
猜你喜歡
類似文章
Spring循環(huán)依賴案例分析:三級緩存結(jié)構(gòu) 循環(huán)依賴解決方案
UC頭條:spring
Spring循環(huán)依賴及解決方式
由spring管理struts的Action實(shí)例
【第三章】 DI 之 3.4 Bean的作用域 ——跟我學(xué)spring3
Spring 如何解決循環(huán)依賴問題?
更多類似文章 >>
生活服務(wù)
分享 收藏 導(dǎo)長圖 關(guān)注 下載文章
綁定賬號成功
后續(xù)可登錄賬號暢享VIP特權(quán)!
如果VIP功能使用有故障,
可點(diǎn)擊這里聯(lián)系客服!

聯(lián)系客服