Session Bean 封裝業務流程、協調事務、提供遠程訪問,不直接持久化數據(由 Entity Bean/JPA 負責)。其實例生命周期由容器管理,支持聲明式事務、安全、並發控制。
| 維度 | Stateful Session Bean (SFSB) | Stateless Session Bean (SLSB) |
|---|---|---|
| 狀態保持 | 維護客戶會話狀態(實例字段) | 無實例狀態,線程安全 |
| 實例關聯 | 專屬於單一客戶 | 池化共享,任意客戶調用 |
| 激活/鈍化 | 容器自動序列化/反序列化至磁盤 | 無需 |
| 典型場景 | 購物車、多步向導、用戶會話上下文 | CRUD 服務、批量處理、工具類方法、Web Service 端點 |
| 性能/擴展性 | 較差(佔用內存、需鈍化) | 極佳(池化、高併發、易集群) |
| 事務邊界 | 跨方法調用維持事務 | 單方法內完成事務 |
javax.ejb.SessionBean(EJB 2.x)或無介口(EJB 3+ 用註解)。ejbCreate(...):初始化邏輯,參數/返回類型符合 RMI-IIOP(可序列化、非基本類型用包裝類)。setSessionContext(SessionContext ctx):容器注入上下文,可獲取 UserTransaction、EJBHome、安全主體等。ejbActivate()/ejbPassivate():SFSB 鈍化/激活鉤子,釋放/恢復非序列化資源(JDBC 連接、Socket、線程)。ejbRemove():清理資源。public、非 static/final、拋出 RemoteException (EJB 2.x) 或應用異常。create(...) 對應 ejbCreate,拋出 CreateException、RemoteException。Remote 介口(EJB 2.x)或 Bean 本地/遠程視圖(EJB 3+)。create();SFSB 可多重載 create(...) 接收初始化參數。RemoteException (EJB 2.x) 或應用異常(EJB 3+ 不強制)。// 無狀態:預設池化、線程安全、高性能
@Stateless
@Remote(OrderService.class)
public class OrderServiceBean implements OrderService {
@PersistenceContext
private EntityManager em;
@Resource
private SessionContext ctx;
@TransactionAttribute(TransactionAttributeType.REQUIRED)
public Order createOrder(Customer customer, List items) {
Order order = new Order(customer);
for (OrderItem item : items) {
order.addItem(item);
em.persist(item);
}
em.persist(order);
return order;
}
@TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED)
public Order findOrder(Long id) {
return em.find(Order.class, id);
}
}
// 有狀態:維護會話狀態,需客戶端保持引用
@Stateful
@Remote(ShoppingCart.class)
public class ShoppingCartBean implements ShoppingCart {
private List- items = new ArrayList<>();
@PostConstruct
public void init() { items.clear(); }
public void addItem(Item item) { items.add(item); }
public List
- getItems() { return Collections.unmodifiableList(items); }
@Remove
@TransactionAttribute(TransactionAttributeType.REQUIRED)
public void checkout(PaymentInfo payment) {
// 處理訂單、付款、清空購物車
items.clear();
}
@PrePassivate
public void passivate() { /* 釋放非序列化資源 */ }
@PostActivate
public void activate() { /* 恢復資源 */ }
}
@AccessTimeout),並發性能差;SLSB 天然並發。| 錯誤 | 後果 | 修正 |
|---|---|---|
| SLSB 使用實例字段保存請求數據 | 線程安全 Bug,數據錯亂 | 改用方法局部變量或 ThreadLocal |
| SFSB 未實現 Serializable | 鈍化失敗,容器報錯 | 實現 Serializable,聲明 serialVersionUID |
| 業務方法拋出 RuntimeException 導致事務回滾但未記錄日誌 | 難以排查 | 捕獲轉為應用異常或用 @ApplicationException(rollback=true) |
| Remote 介口傳遞 Entity Bean 實例 | 序列化巨大對象圖,性能災難 | 傳遞 DTO/VO,或用 JPA 脫管實體 |
Session Bean 是 EJB 容器管理業務邏輯的核心組件。Stateless 為默認首選,Stateful 僅在確需會話狀態時使用。EJB 3+ 註解極大簡化了開發,但對生命周期、事務屬性、序列化、併發語義的理解仍是寫出健壯企業級應用的關鍵。現代架構常以 Spring + JPA 替代 EJB,但其核心概念(事務邊界、狀態管理、容器服務)具有普世價值。