一区二区三区在线-一区二区三区亚洲视频-一区二区三区亚洲-一区二区三区午夜-一区二区三区四区在线视频-一区二区三区四区在线免费观看

服務器之家:專注于服務器技術及軟件下載分享
分類導航

PHP教程|ASP.NET教程|JAVA教程|ASP教程|編程技術|正則表達式|C/C++|IOS|C#|Swift|Android|JavaScript|易語言|

服務器之家 - 編程語言 - JAVA教程 - 淺談Spring解決循環依賴的三種方式

淺談Spring解決循環依賴的三種方式

2021-02-06 12:25學習園 JAVA教程

本篇文章主要介紹了淺談Spring循環依賴的三種方式,小編覺得挺不錯的,現在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧

引言:循環依賴就是n個類中循環嵌套引用,如果在日常開發中我們用new 對象的方式發生這種循環依賴的話程序會在運行時一直循環調用,直至內存溢出報錯。下面說一下spring是如果解決循環依賴的。

第一種:構造器參數循環依賴

表示通過構造器注入構成的循環依賴,此依賴是無法解決的,只能拋出beancurrentlyin creationexception異常表示循環依賴。

如在創建testa類時,構造器需要testb類,那將去創建testb,在創建testb類時又發現需要testc類,則又去創建testc,最終在創建testc時發現又需要testa,從而形成一個環,沒辦法創建。

spring容器會將每一個正在創建的bean 標識符放在一個“當前創建bean池”中,bean標識符在創建過程中將一直保持
在這個池中,因此如果在創建bean過程中發現自己已經在“當前創建bean池”里時將拋出
beancurrentlyincreationexception異常表示循環依賴;而對于創建完畢的bean將從“當前創建bean池”中清除掉。

首先我們先初始化三個bean。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public class studenta {
 
 private studentb studentb ;
 
 public void setstudentb(studentb studentb) {
 this.studentb = studentb;
 }
 
 public studenta() {
 }
 
 public studenta(studentb studentb) {
 this.studentb = studentb;
 }
}
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public class studentb {
 
 private studentc studentc ;
 
 public void setstudentc(studentc studentc) {
 this.studentc = studentc;
 }
 
 public studentb() {
 }
 
 public studentb(studentc studentc) {
 this.studentc = studentc;
 }
}
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public class studentc {
 
 private studenta studenta ;
 
 public void setstudenta(studenta studenta) {
 this.studenta = studenta;
 }
 
 public studentc() {
 }
 
 public studentc(studenta studenta) {
 this.studenta = studenta;
 }
}

ok,上面是很基本的3個類,,studenta有參構造是studentb。studentb的有參構造是studentc,studentc的有參構造是studenta ,這樣就產生了一個循環依賴的情況,我們都把這三個bean交給spring管理,并用有參構造實例化

?
1
2
3
4
5
6
7
8
9
<bean id="a" class="com.zfx.student.studenta">
 <constructor-arg index="0" ref="b"></constructor-arg>
</bean>
<bean id="b" class="com.zfx.student.studentb">
 <constructor-arg index="0" ref="c"></constructor-arg>
</bean>
<bean id="c" class="com.zfx.student.studentc">
 <constructor-arg index="0" ref="a"></constructor-arg>
</bean>

下面是測試類:

?
1
2
3
4
5
6
public class test {
 public static void main(string[] args) {
 applicationcontext context = new classpathxmlapplicationcontext("com/zfx/student/applicationcontext.xml");
 //system.out.println(context.getbean("a", studenta.class));
 }
}

執行結果報錯信息為:

caused by: org.springframework.beans.factory.beancurrentlyincreationexception:  
    error creating bean with name 'a': requested bean is currently in creation: is there an unresolvable circular reference? 

如果大家理解開頭那句話的話,這個報錯應該不驚訝,spring容器先創建單例studenta,studenta依賴studentb,然后將a放在“當前創建bean池”中,此時創建studentb,studentb依賴studentc ,然后將b放在“當前創建bean池”中,此時創建studentc,studentc又依賴studenta, 但是,此時student已經在池中,所以會報錯,,因為在池中的bean都是未初始化完的,所以會依賴錯誤 ,(初始化完的bean會從池中移除)

第二種:setter方式單例,默認方式

如果要說setter方式注入的話,我們最好先看一張spring中bean實例化的圖

淺談Spring解決循環依賴的三種方式

如圖中前兩步驟得知:spring是先將bean對象實例化之后再設置對象屬性的

修改配置文件為set方式注入

?
1
2
3
4
5
6
7
8
9
10
<!--scope="singleton"(默認就是單例方式) -->
<bean id="a" class="com.zfx.student.studenta" scope="singleton">
 <property name="studentb" ref="b"></property>
</bean>
<bean id="b" class="com.zfx.student.studentb" scope="singleton">
 <property name="studentc" ref="c"></property>
</bean>
<bean id="c" class="com.zfx.student.studentc" scope="singleton">
 <property name="studenta" ref="a"></property>
</bean>

下面是測試類:

?
1
2
3
4
5
6
public class test {
 public static void main(string[] args) {
 applicationcontext context = new classpathxmlapplicationcontext("com/zfx/student/applicationcontext.xml");
 system.out.println(context.getbean("a", studenta.class));
 }
}

打印結果為:

com.zfx.student.studenta@1fbfd6 

為什么用set方式就不報錯了呢 ?

我們結合上面那張圖看,spring先是用構造實例化bean對象 ,此時spring會將這個實例化結束的對象放到一個map中,并且spring提供了獲取這個未設置屬性的實例化對象引用的方法。   結合我們的實例來看,,當spring實例化了studenta、studentb、studentc后,緊接著會去設置對象的屬性,此時studenta依賴studentb,就會去map中取出存在里面的單例studentb對象,以此類推,不會出來循環的問題嘍、

下面是spring源碼中的實現方法,。以下的源碼在spring的bean包中的defaultsingletonbeanregistry.java類中

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
/** cache of singleton objects: bean name --> bean instance(緩存單例實例化對象的map集合) */
 private final map<string, object> singletonobjects = new concurrenthashmap<string, object>(64);
 
 /** cache of singleton factories: bean name --> objectfactory(單例的工廠bean緩存集合) */
 private final map<string, objectfactory> singletonfactories = new hashmap<string, objectfactory>(16);
 
 /** cache of early singleton objects: bean name --> bean instance(早期的單身對象緩存集合) */
 private final map<string, object> earlysingletonobjects = new hashmap<string, object>(16);
 
 /** set of registered singletons, containing the bean names in registration order(單例的實例化對象名稱集合) */
 private final set<string> registeredsingletons = new linkedhashset<string>(64);
 /**
 * 添加單例實例
 * 解決循環引用的問題
 * add the given singleton factory for building the specified singleton
 * if necessary.
 * <p>to be called for eager registration of singletons, e.g. to be able to
 * resolve circular references.
 * @param beanname the name of the bean
 * @param singletonfactory the factory for the singleton object
 */
 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);
  }
 }
 }

第三種:setter方式原型,prototype

對于"prototype"作用域bean,spring容器無法完成依賴注入,因為spring容器不進行緩存"prototype"作用域的bean,因此無法提前暴露一個創建中的bean。

修改配置文件為:

?
1
2
3
4
5
6
7
8
9
<bean id="a" class="com.zfx.student.studenta" <span style="color:#ff0000;">scope="prototype"</span>>
 <property name="studentb" ref="b"></property>
 </bean>
 <bean id="b" class="com.zfx.student.studentb" <span style="color:#ff0000;">scope="prototype"</span>>
 <property name="studentc" ref="c"></property>
 </bean>
 <bean id="c" class="com.zfx.student.studentc" <span style="color:#ff0000;">scope="prototype"</span>>
 <property name="studenta" ref="a"></property>
 </bean>

scope="prototype" 意思是 每次請求都會創建一個實例對象。兩者的區別是:有狀態的bean都使用prototype作用域,無狀態的一般都使用singleton單例作用域。

測試用例:

?
1
2
3
4
5
6
7
public class test {
 public static void main(string[] args) {
 applicationcontext context = new classpathxmlapplicationcontext("com/zfx/student/applicationcontext.xml");
 <strong>//此時必須要獲取spring管理的實例,因為現在scope="prototype" 只有請求獲取的時候才會實例化對象</strong>
 system.out.println(context.getbean("a", studenta.class));
 }
}

打印結果:

caused by: org.springframework.beans.factory.beancurrentlyincreationexception:  
    error creating bean with name 'a': requested bean is currently in creation: is there an unresolvable circular reference? 

為什么原型模式就報錯了呢 ?

對于“prototype”作用域bean,spring容器無法完成依賴注入,因為“prototype”作用域的bean,spring容
器不進行緩存,因此無法提前暴露一個創建中的bean。

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持服務器之家。

原文鏈接:http://blog.csdn.net/u010644448/article/details/59108799

延伸 · 閱讀

精彩推薦
  • JAVA教程基于Spring + Spring MVC + Mybatis 高性能web構建實例詳解

    基于Spring + Spring MVC + Mybatis 高性能web構建實例詳解

    這篇文章主要介紹了基于Spring + Spring MVC + Mybatis 高性能web構建實例詳解,需要的朋友可以參考下...

    夢想合伙人2262020-09-12
  • JAVA教程java之super關鍵字用法實例解析

    java之super關鍵字用法實例解析

    這篇文章主要介紹了java之super關鍵字用法實例解析,較為詳細的分析了super關鍵字的用法及內存分布,需要的朋友可以參考下 ...

    shichen20143932019-12-01
  • JAVA教程springAOP的三種實現方式示例代碼

    springAOP的三種實現方式示例代碼

    這篇文章主要介紹了springAOP的三種實現方式,本文通過實例代碼給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考...

    易水寒的博客2522020-07-21
  • JAVA教程25個最好的免費Eclipse插件

    25個最好的免費Eclipse插件

    這篇文章為大家分享了25個讓Java程序員更高效的Eclipse插件,感興趣的朋友可以參考一下 ...

    Sunshine_lily5952020-03-10
  • JAVA教程java計算集合對稱差的示例代碼

    java計算集合對稱差的示例代碼

    本篇文章主要介紹了java計算集合對稱差的示例代碼,小編覺得挺不錯的,現在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧...

    xixicat4302020-12-24
  • JAVA教程Java 正則表達式詳細介紹

    Java 正則表達式詳細介紹

    本文主要介紹 Java 正則表達式的內容,這里整理了Java 正則表達式的相關資料,并詳細介紹,附有代碼示例,有興趣的小伙伴可以參考下...

    kdnuggets1992020-06-10
  • JAVA教程java微信公眾號開發案例

    java微信公眾號開發案例

    這篇文章主要為大家詳細介紹了java微信公眾號開發案例,如何接入公眾號,訂閱號怎么樣接收消息,具有一定的參考價值,感興趣的小伙伴們可以參考一下...

    偉雪無痕3862020-07-06
  • JAVA教程詳解Java中@Override的作用

    詳解Java中@Override的作用

    這篇文章主要介紹了詳解Java中@Override的作用的相關資料,希望通過本文能幫助到大家,讓大家理解這部分內容,需要的朋友可以參考下...

    _QING_FENG5972021-01-19
主站蜘蛛池模板: 蘑菇香蕉茄子绿巨人丝瓜草莓 | 免费看60分钟大片视频播放 | 男gay网站视频免费观看 | 催眠白丝舞蹈老师小说 | 精品欧美男同同性videos | 欧美午夜性春猛交bbb | 碰91精品国产91久久婷婷 | 国产在线激情视频 | 大胆私拍模特国模377 | 成 人 亚洲 综合天堂 | 国产永久在线观看 | 国产高清露脸学生在线观看 | 2021国产麻豆剧传媒剧情 | 激情文学综合网 | 精品综合久久久久久88小说 | 男人影院天堂网址 | 天天干女人 | 日本色网址 | 91看片淫黄大片.在线天堂 | 日本精工厂网址 | 亚洲日本aⅴ片在线观看香蕉 | 脱jk裙的美女露小内内无遮挡 | a级精品九九九大片免费看 a级动漫 | 按摩院已婚妇女中文字幕 | 欧美破处摘花 | 乖女的嫩奶水h文孕妇 | 天堂bt在线 | 暖暖日本在线观看免费 | 99亚洲| 亚洲国产综合久久精品 | 亚洲高清中文字幕一区二区三区 | 男人天堂国产 | 国产青草亚洲香蕉精品久久 | 亚洲AV蜜桃永久无码精品红樱桃 | 日韩不卡一区二区三区 | 日本妻子迷妹网 | 国产成人99精品免费观看 | 日本精品一二三区 | 好湿好紧太硬了我好爽 | 操熟美女又肥又嫩的骚屁股 | 欧美人与日本人xx在线视频 |