欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Spring Bean Scope 有狀態(tài)的Bean與無狀態(tài)的Bean

 更新時(shí)間:2022年01月20日 10:20:43   作者:cs408 ?  
這篇文章主要介紹了Spring Bean Scope 有狀態(tài)的Bean與無狀態(tài)的Bean,每個(gè)用戶有自己特有的一個(gè)實(shí)例,在用戶的生存期內(nèi),bean保持了用戶的信息,下面來了解有狀態(tài)和無狀態(tài)的區(qū)別吧

有狀態(tài)會(huì)話bean:每個(gè)用戶有自己特有的一個(gè)實(shí)例,在用戶的生存期內(nèi),bean保持了用戶的信息,即“有狀態(tài)”;一旦用戶滅亡(調(diào)用結(jié)束或?qū)嵗Y(jié)束),bean的生命期也告結(jié)束。即每個(gè)用戶最初都會(huì)得到一個(gè)初始的bean。   
    
  無狀態(tài)會(huì)話bean:bean一旦實(shí)例化就被加進(jìn)會(huì)話池中,各個(gè)用戶都可以共用。即使用戶已經(jīng)消亡,bean   的生命期也不一定結(jié)束,它可能依然存在于會(huì)話池中,供其他用戶調(diào)用。由于沒有特定的用戶,那么也就不能保持某一用戶的狀態(tài),所以叫無狀態(tài)bean。但無狀態(tài)會(huì)話bean   并非沒有狀態(tài),如果它有自己的屬性(變量),那么這些變量就會(huì)受到所有調(diào)用它的用戶的影響,這是在實(shí)際應(yīng)用中必須注意的。

在Spring的Bean配置中,存在這樣兩種情況:

<bean id="testManager" class="com.sw.TestManagerImpl" scope="singleton" /> ?
??
?<bean id="testManager" class="com.sw.TestManagerImpl" scope="prototype" /> ?

當(dāng)然,scope的值不止這兩種,還包括了request,session 等。但用的最多的還是singleton單態(tài),prototype多態(tài)。

singleton表示該bean全局只有一個(gè)實(shí)例,Spring中bean的scope默認(rèn)也是singleton.

prototype表示該bean在每次被注入的時(shí)候,都要重新創(chuàng)建一個(gè)實(shí)例,這種情況適用于有狀態(tài)的Bean.

對(duì)于SSH架構(gòu)的系統(tǒng),很少關(guān)心這方面,因?yàn)槲覀冇玫降囊话愣际莝ingleton. Bean的注入由Spring管理。

對(duì)于有狀態(tài)的Bean呢?

下面是一個(gè)有狀態(tài)的Bean:

package com.sw; ?
??
public class TestManagerImpl implements TestManager{ ?
? ? private User user; ? ?
??
? ? public void deleteUser(User e) throws Exception { ?
? ? ? ? user = e ; ? ? ? ? ? //1 ?
? ? ? ? prepareData(e); ?
? ? } ?
??
? ? public void prepareData(User e) throws Exception { ?
? ? ? ? user = getUserByID(e.getId()); ? ? ? ? ? ?//2 ?
? ? ? ? ..... ?
? ? ? ? //使用user.getId(); ? ? ? ? ? ? ? ? ? ? ? //3 ?
? ? ? ? ..... ?
? ? ? ? ..... ?
? ? } ? ??
} ?

如果該Bean配置為singleton,會(huì)出現(xiàn)什么樣的狀況呢?

如果有2個(gè)用戶訪問,都調(diào)用到了該Bean.

假定為user1,user2

當(dāng)user1 調(diào)用到程序中的1步驟的時(shí)候,該Bean的私有變量user被付值為user1

當(dāng)user1的程序走到2步驟的時(shí)候,該Bean的私有變量user被重新付值為user1_create

理想的狀況,當(dāng)user1走到3步驟的時(shí)候,私有變量user應(yīng)該為user1_create;

但如果在user1調(diào)用到3步驟之前,user2開始運(yùn)行到了1步驟了,由于單態(tài)的資源共享,則私有變量user被修改為user2

這種情況下,user1的步驟3用到的user.getId()實(shí)際用到是user2的對(duì)象。(我的理解是配置成singleton會(huì)造成資源混亂問題-對(duì)于有狀態(tài)的bean)

而如果是prototype的話,就不會(huì)出現(xiàn)資源共享的問題。(即不會(huì)出現(xiàn)線程安全的問題)

對(duì)于SSH來說,Bean的配置是沒錯(cuò)的,配置為singleton ;

實(shí)際應(yīng)該是這個(gè)例子不應(yīng)該用私有變量,這樣就使得這個(gè)Bean由無狀態(tài)變成了有狀態(tài)Bean.

還是應(yīng)該盡量使用無狀態(tài)Bean.如果在程序中出現(xiàn)私有變量(該bean會(huì)變?yōu)橛袪顟B(tài)的,一旦在其他線程中發(fā)生改變,就會(huì)產(chǎn)生線程不安全),解決方案就是盡量替換為方法中的參數(shù)。
對(duì)于每個(gè)訪問私有變量的方法增加變量傳入(參數(shù)傳入)或者通過ThreadLocal來獲取也是不錯(cuò)的方法。(重點(diǎn)解決方案,可以防止多線程帶來的不安全問題)

真正出現(xiàn)上面代碼問題的也是少數(shù),出現(xiàn)的時(shí)候,一般是為了圖方便,使用了一個(gè)很多方法都要用到的變量(變量在傳遞過程中發(fā)生改變,就會(huì)產(chǎn)生多線程不安全問題)。如果變量都需要用參數(shù)的方式傳遞多麻煩呀,這樣私有變量多好,不用參數(shù)那樣丑陋。但是丑陋并不代表不好,以對(duì)的,自己習(xí)慣的方式編程,才能盡量避免問題的發(fā)生。

引申:

Spring中的有狀態(tài)(Stateful)和無狀態(tài)(Stateless) (web中的并發(fā)通過單例可以避免)

  • 1.通過上面的分析,相信大家已經(jīng)對(duì)有狀態(tài)和無狀態(tài)有了一定的理解。無狀態(tài)的Bean適合用不變模式,技術(shù)就是單例模式,這樣可以共享實(shí)例,提高性能。有狀態(tài)的Bean,多線程環(huán)境下不安全,那么適合用Prototype原型模式(解決多線程問題)。Prototype: 每次對(duì)bean的請(qǐng)求都會(huì)創(chuàng)建一個(gè)新的bean實(shí)例。 
  • 2.默認(rèn)情況下,從Spring bean工廠所取得的實(shí)例為singleton(scope屬性為singleton),容器只存在一個(gè)共享的bean實(shí)例。 
  • 3.理解了兩者的關(guān)系,那么scope選擇的原則就很容易了:有狀態(tài)的bean都使用prototype作用域,而對(duì)無狀態(tài)的bean則應(yīng)該使用singleton作用域。 
  • 4.如Service層、Dao層用默認(rèn)singleton就行,雖然Service類也有dao這樣的屬性,但dao這些類都是沒有狀態(tài)信息的,也就是相當(dāng)于不變(immutable)類,所以不影響。Struts2中的Action因?yàn)闀?huì)有User、BizEntity這樣的實(shí)例對(duì)象,是有狀態(tài)信息的,在多線程環(huán)境下是不安全的,所以Struts2默認(rèn)的實(shí)現(xiàn)是Prototype模式。在Spring中,Struts2的Action中,scope要配成prototype作用域。 

Servlet、Struts中的有狀態(tài)和無狀態(tài): 

1.Servlet體系結(jié)構(gòu)是建立在Java多線程機(jī)制之上的,它的生命周期是由Web 容器負(fù)責(zé)的。一個(gè)Servlet類在Application中只有一個(gè)實(shí)例存在,也就是有多個(gè)線程在使用這個(gè)實(shí)例。這是單例模式的應(yīng)用。無狀態(tài)的單例是線程安全的,但我們?nèi)绻赟ervlet里用了實(shí)例變量(私有變量),那么就變成有狀態(tài)了,是非線程安全的。如下面的用法就是不安全的,因?yàn)閡ser,out都是有狀態(tài)信息的。 

/**?
?* 非線程安全的Servlet。?
?* @author Peter Wei?
?*?
?*/ ?
public class UnSafeServlet HttpServlet{ ?
? ? ??
? ? User user; ?
? ? PrintWriter out; ?
? ? ??
? ? public void doGet (HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException{ ?
? ? ? ? //do something... ?
? ? } ?
} ?

Out,Request,Response,Session,Config,Page,PageContext是線程安全的,Application在整個(gè)系統(tǒng)內(nèi)被使用,所以不是線程安全的. 

2.Struts1也是基于單例模式實(shí)現(xiàn),也就是只有一個(gè)Action實(shí)例供多線程使用。默認(rèn)的模式是前臺(tái)頁(yè)面數(shù)據(jù)通過actionForm傳入,在action中的excute方法接收,這樣action是無狀態(tài)的,所以一般情況下Strunts1是線程安全的。如果Action中用了實(shí)例變量,那么就變成有狀態(tài)了,同樣是非線程安全的。像下面這樣就是線程不安全的。 

/**?
?* 非線程安全的Struts1示例?
?* ?
?* @author Peter Wei?
?* ?
?*/ ?
public class UnSafeAction1 extends Action { ?
??
? ? // 因?yàn)镾truts1是單例實(shí)現(xiàn),有狀態(tài)情況下,對(duì)象引用是非線程安全的 ?
? ? User user; ?
??
? ? public void execute() { ?
? ? ? ? // do something... ?
? ? } ?
??
? ? public User getUser() { ?
? ? ? ? return user; ?
? ? } ?
??
? ? public void setUser(User user) { ?
? ? ? ? this.user = user; ?
? ? } ?
} ? ?

3.Struts2默認(rèn)的實(shí)現(xiàn)是Prototype模式。也就是每個(gè)請(qǐng)求都新生成一個(gè)Action實(shí)例,所以不存在線程安全問題。需要注意的是,如果由Spring管理action的生命周期, scope要配成prototype作用域。 

4.如何解決Servlet和Struts1的線程安全問題,當(dāng)我們能比較好的理解有狀態(tài)和無狀態(tài)的原理,自然很容易得出結(jié)論: 不要使用有狀態(tài)的bean,也就是不要用實(shí)例變量(私有變量) 。如果用有狀態(tài)的bean,就要用prototype模式,每次在注入的時(shí)候就重新創(chuàng)建一個(gè)bean,在多線程中互不影響。Struts1 user guide里有: Only Use Local Variables - The most important principle that aids in thread-safe coding is to use only local variables, not instance variables , in your Action class. 

總結(jié):  

Stateless無狀態(tài)用單例Singleton模式,Stateful有狀態(tài)就用原型Prototype模式。  
Stateful 有狀態(tài)是多線程編碼的天敵,所以在開發(fā)中盡量用Stateless無狀態(tài),無狀態(tài)是不變(immutable)模式的應(yīng)用,有很多優(yōu)點(diǎn):不用管線程和同步的問題 ,如果值是不可變的,程序不用擔(dān)心多個(gè)線程改變共享狀態(tài),所以可以避免線程競(jìng)爭(zhēng)的bugs. 因?yàn)闆]有競(jìng)爭(zhēng),就不用用locks等機(jī)制,所以無狀態(tài)的不變機(jī)制,也可以避免產(chǎn)生死鎖現(xiàn)象。 

到此這篇關(guān)于Spring Bean Scope 有狀態(tài)的Bean與無狀態(tài)的Bean的文章就介紹到這了,更多相關(guān) 有狀態(tài)的Bean與無狀態(tài)的Bean內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Kotlin與java8的SAM轉(zhuǎn)換對(duì)比(進(jìn)階)

    Kotlin與java8的SAM轉(zhuǎn)換對(duì)比(進(jìn)階)

    這篇文章主要介紹了Kotlin與java8的SAM轉(zhuǎn)換對(duì)比,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-05-05
  • java String 轉(zhuǎn)成Double二維數(shù)組的方法

    java String 轉(zhuǎn)成Double二維數(shù)組的方法

    下面小編就為大家?guī)硪黄猨ava String 轉(zhuǎn)成Double二維數(shù)組的方法。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2016-10-10
  • Java連接超時(shí)的幾種情況以及讀取代碼

    Java連接超時(shí)的幾種情況以及讀取代碼

    在Java編程中連接超時(shí)異常是指在建立網(wǎng)絡(luò)連接時(shí),無法在給定的時(shí)間內(nèi)成功建立連接的異常,這篇文章主要給大家介紹了關(guān)于Java連接超時(shí)的幾種情況以及讀取的相關(guān)資料,需要的朋友可以參考下
    2024-02-02
  • 解決使用ProcessBuilder踩到的坑及注意事項(xiàng)

    解決使用ProcessBuilder踩到的坑及注意事項(xiàng)

    這篇文章主要介紹了解決使用ProcessBuilder踩到的坑,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-06-06
  • Java 如何實(shí)現(xiàn)解壓縮文件和文件夾

    Java 如何實(shí)現(xiàn)解壓縮文件和文件夾

    這篇文章主要介紹了Java 如何實(shí)現(xiàn)解壓縮文件和文件夾,幫助大家更好的理解和學(xué)習(xí)使用Java,感興趣的朋友可以了解下
    2021-03-03
  • MyBatis-Plus多數(shù)據(jù)源的示例代碼

    MyBatis-Plus多數(shù)據(jù)源的示例代碼

    本文主要介紹了MyBatis-Plus多數(shù)據(jù)源的示例代碼,包括依賴配置、數(shù)據(jù)源配置、Mapper 和 Service 的定義,具有一定的參考價(jià)值,感興趣的可以了解一下
    2024-05-05
  • 如何在Eclipse中設(shè)置Oracle的JDBC

    如何在Eclipse中設(shè)置Oracle的JDBC

    以下是對(duì)在Eclipse中設(shè)置Oracle的JDBC的具體操作方法進(jìn)行了詳細(xì)的分析介紹,需要的朋友可以過來參考下
    2013-08-08
  • springboot接收日期類型參數(shù)的操作方法

    springboot接收日期類型參數(shù)的操作方法

    如果使用Get請(qǐng)求,直接使用對(duì)象接收,則可以使用@DateTimeFormat注解進(jìn)行格式化,本文重點(diǎn)給大家介紹springboot接收日期類型參數(shù)的方法,感興趣的朋友一起看看吧
    2024-02-02
  • java類的加載過程以及類加載器的分析

    java類的加載過程以及類加載器的分析

    這篇文章給大家詳細(xì)講述了java類的加載過程以及類加載器的相關(guān)知識(shí)點(diǎn)內(nèi)容,有需要的朋友可以學(xué)習(xí)下。
    2018-08-08
  • 深入了解Spring中的依賴注入DI

    深入了解Spring中的依賴注入DI

    這篇文章主要介紹了Spring?中的依賴注入,包括注入的方式,寫法,該選擇哪個(gè)注入方式以及可能出現(xiàn)的循環(huán)依賴問題等內(nèi)容,需要的可以參考一下
    2023-06-06

最新評(píng)論