單例會話bean(1)

EJB3.1之前在會話bean的種類中是沒有單例會話bean的,有的只是有狀態會話bean以及無狀態會話bean。毋庸置疑無狀態會話bean以其優秀的性能被普遍使用,但是人們發現在無狀態會話bean在使用過程中有兩個最常值得關注的問題。按照官方一點兒的話說那就是一、bean池的感知開銷。二、無法通過靜態字段共享狀態。其中第二點很好理解,因爲無狀態會話bean在每次請求的時候都需要從實例池中拿到一個實例對請求進行服務所以不可能存在像普通java變量那樣通過共享靜態字段共享不同請求之間的狀態。第一點所謂的感知開銷是指客戶端發起請求的時候bean池不知道還有多少個實例可用,bean池所做的就是將請求放在一個隊列中然後等待可用的實例,然後將這個實例拿出來對請求進行服務。

單例會話bean的出現實現了單個共享的bean實例,爲上面兩個問題提供瞭解決方案,這個共享bean既可以併發訪問(解決第一個關於bean池感知開銷的問題),也可以作爲一種共享狀態的機制(共享不同會話之間的狀態)。單例會話bean與無狀態會話bean的生命週期回調是相同的但生命週期是完全不同的,爲了能夠進行同步在單例會話bean中還了複雜的開發人員控制鎖(developer-controlledlocking)。

與其他會話bean不同,單例會話bean在應用程序初始化期間迅速創建單例,同時在應用程序關閉之前一直存在。可以這麼認爲,當應用程序啓動這個單例就一直存在知道服務器停止。也就是說單例會話bean一旦創建了,它就將在容器刪除它之前一直存在,無論在業務方法執行過程中是否發生任何異常。這是它與其他會話bean類型之間的一個關鍵差異,因爲永遠不會在系統異常事件中重新創建這種bean實例。

因爲單例會話bean的聲明週期很長,並且能夠共享實例,所以常見應用程序狀態的理想儲存位置就落在了它的頭上,無論是隻讀(read-only)狀態還是讀寫(read-write)狀態。爲了確保訪問這種狀態,單例會話bean提供了許多併發選項,它們取決於應用程序開發人員的需要。考慮到性能,方法可能完全不同步,或者由容器自動地鎖定和管理。

1.定義單例會話bean

和無狀態和有狀態會話bean的模型一樣,單例會話bean使用@Singleton註解來定義。單例會話bean可以包括一個本地業務接口或者使用一個無接口視圖。下面代碼顯示了一個簡單的具有無接口視圖的單例會話bean,用於跟蹤Web站點的訪問次數。

@Singleton
public class HitCounter {
	int count;

	public void increment() { ++count; }
	
	@Lock(LockType.READ)
	public int getCount() { return count; }

    public void reset() { count = 0; }
}

如果將上面程序中的HitCounterbean與前面定義的無狀態與有狀態會話bean進行比較,那麼立刻可以看到兩個差異。與無狀態會話bean不同,它存在計數字段形式的狀態,用於捕獲訪問計數(保存了會話的狀態,而且在不同會話之間是共享的)。與有狀態會話bean也不同,沒有包含@Remove註解以標識用於完成會話的業務方法(表明單例會話bean不會被銷燬)。

默認情況下,容器將管理業務方法的同步以確保不會發生數據破壞。在此例中,這意味着對於bean的所有訪問進行序列化,從而保證在任何時間只有一個客戶端調用該實例的業務方法。

單例會話bean的生命週期關係到整個應用程序的生命週期。容器決定何時創建單例實例的時間,(如果該bean同時包括@Startup註解,那麼應用程序將會強制在啓動時迅速初始化這個單例會話bean的實例)。容器當然也可以創建不被@Startup註解標記的在系統應用程序啓動時初始化的singleton,但這是特定於不同的服務器供應商的,JavaEE中沒有做表述。

當多個單例會話bean互相依賴時,需要告知容器對它們進行實例化的順序。這時可以通過在bean類中的添加@DependsOn註解來實現,其中列出了其他必須提前創建的單例會話bean的名稱(如果多個記得逗號隔開)。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章