常見誤區
許多人誤以為:
- 有狀態 = 實例永遠存在,保留每次呼叫狀態
- 無狀態 = 每次呼叫新建實例,不保留用戶資訊
實際上恰好相反,本質差異在於生命週期。
核心概念:什麼是「用戶」?
Session Bean 的用戶 = 直接呼叫 EJB 的類別實例(甚至是該實例的某個方法)。同一類別的不同實例 = 不同用戶。
有狀態 Session Bean(Stateful)
- 專屬實例:每個用戶擁有自己專屬的 Bean 實例
- 生命週期綁定用戶:用戶存活期間,Bean 保持用戶狀態(「有狀態」);用戶消亡(呼叫結束或實例銷毀),Bean 生命週期結束
- 初始狀態:每個用戶最初獲得一個初始化的 Bean
無狀態 Session Bean(Stateless)
- 共用實例池:Bean 實例化後放入池中,所有用戶共用
- 生命週期獨立於用戶:用戶消亡不代表 Bean 結束,實例留在池中供下一個用戶使用
- 無專屬狀態:因無特定用戶,無法保持特定用戶狀態,故稱「無狀態」
- 但非完全無狀態:若 Bean 有屬性變數,會受所有呼叫者影響,實務上必須注意
比較總結表
| 特性 | Stateful Bean | Stateless Bean |
| 實例擁有權 | 專屬單一用戶 | 池化共用 |
| 狀態保持 | 跨方法呼叫保持 | 不保持用戶狀態 |
| 生命週期 | 隨用戶建立/銷毀 | 由容器管理池化 |
| 適用場景 | 購物車、多步驟流程 | 單一業務操作、高併發 |
實務建議
- Stateless Bean 盡量避免使用實例變數,若必須用,需為執行緒安全設計
- Stateful Bean 適合會話式交互,但需注意併發存取限制(同一實例同一時間只能服務一個用戶)
- 選擇原則:有跨請求狀態需求 → Stateful;單一獨立操作、追求高擴展性 → Stateless