EJB3.0 有狀態會話bean無狀態會話bean詳解
在網上看到了這一篇文章詳細描述了兩種會話hean的區別,但因轉載的人實在太多了,所以無法註明原文出處。只好用原創表示,對於文章的原創者,表示尊敬。
下面主要對Session Bean討論
現實中,很多朋友對兩種sessionbean存在誤解,認為有狀態是例項一直存在,儲存每次呼叫後的狀態,並對下一次呼叫起作用,而認為無狀態是每次呼叫例項化一次,不保留使用者資訊。仔細分析並用實踐檢驗後,你會發現,事實恰好相反:有狀態和無狀態會話bean的本質區別是它們的生命期。
首先解釋一個下面要用到的概念--使用者:sessionbean 的使用者實際上就是直接呼叫ejb的類的例項,甚至是這個例項的某個方法。同一個類的不同例項對於session bean來說是不同的使用者。
有狀態會話bean:每個使用者有自己特有的一個例項,在使用者的生存期內,bean保持了使用者的資訊,即“有狀態”;一旦使用者滅亡(呼叫結束或例項結束),bean的生命期也告結束。即每個使用者最初都會得到一個初始的bean。
無狀態會話bean :bean一旦例項化就被加進會話池中,各個使用者都可以共用。即使使用者已經消亡,bean的生命期也不一定結束,它可能依然存在於會話池中,供其他使用者呼叫。由於沒有特定的使用者,那麼也就不能保持某一使用者的狀態,所以叫無狀態bean。但無狀態會話bean並非沒有狀態,如果它有自己的屬性(變數),那麼這些變數就會受到所有呼叫它的使用者的影響,這是在實際應用中必須注意的。
區別的根本原因
這與無狀態會話Bean和有狀態會話Bean的執行原理是相關的。
對於有狀態會話Bean來說,只要有客戶端傳送對有狀態會話Bean的訪問,伺服器都會建立一個會話Bean例項與該客戶端對應,這樣這個例項與這個客戶端就是一一對應的。如果客戶端在Bean例項中儲存了資訊,之後還可以使用。
對於無狀態會話Bean來說,伺服器端會維持一個例項池,建立好若干個例項物件供客戶端呼叫。當從客戶端傳送建立會話Bean的請求時,並不一定會真的建立EJB,多數情況下是從例項池中得到一個例項,用完之後重新放回例項池。如果下次再訪問,再從例項池中取出一個例項使用,並不一定是上次的例項。即使兩次訪問使用的是同一個例項,在兩次訪問之間也有可能有其他的客戶端訪問了該例項。所以,並不能保證在多次訪問之間的資訊會被儲存。所以,無狀態會話Bean不會專門儲存客戶端的資訊。
各自的優缺點
因為有狀態會話Bean需要儲存特定客戶端的資訊,一個客戶端對應一個例項,既是在當時客戶端有連線沒有訪問的情況下,也要為這個客戶端保留這個例項。這樣隨著客戶端數量的增加,伺服器端需要建立的例項的數量也在增加,增加到一定程度對伺服器的效能就會有一定的影響。為了不對伺服器的效能產生影響,通常伺服器會進行一些優化。當客戶端的數量超過某個值之後,就不建立新的例項。雖然不建立新的例項,還是需要對使用者響應,這時候就採用共享例項的方式。會檢視哪個例項雖然處於連線狀態,但是沒有訪問,然後把這個例項的狀態儲存起來,使用這個例項為新的請求服務,對於原來的客戶端來說,稱為掛起。如果原來的客戶端又傳送請求了,會重新查詢一個空閒的例項並且把已經儲存好的狀態恢復回來,這個過程稱為啟用。所以在有狀態會話Bean的訪問過程,經常會發生查詢例項,啟用掛起等操作,所以效率比較低。
而傳送對無狀態會話Bean的請求的時候,可以隨便取一個空閒的例項為客戶端服務,所以效率比較高。
有狀態會話Bean的好處是,可以儲存客戶端的狀態,所以客戶端在後續訪問的時候就可以少傳遞一些引數。而無狀態會話Bean需要傳遞方法執行過程中需要的所有引數。
如何選擇
根據上面分析的有狀態會話Bean和無狀態會話Bean的優缺點。如果要頻繁的訪問,並且多次訪問之間會共享一些資訊,這時候應該使用有狀態會話Bean。對於不經常使用的功能,可以使用無狀態會話Bean。無狀態會話Bean的使用要比有狀態會話Bean的使用多。
專案中沒有使用到有狀態的會話bean,對於使用的相同資料,也是通過傳遞引數實現,並非設定到bean中的屬性值中。對於無狀態的會話bean,如果有屬性,則可能影響到所有呼叫的使用者,因為他是共享的。 如下:
有狀態會話bean。客戶端呼叫,每一個客戶端,列印都將會是從0開始。
無狀態會話bean。客戶端呼叫,每一個客戶端列印的值,可能會在上一個使用者的基礎上累加。因為bean是被共享的。