關鍵差異:有狀態 vs 無狀態
| 特性 | @Stateless | @Stateful |
| 狀態保持 | 不保持(池化複用) | 專屬於單一 Client 會話 |
| 移除機制 | 容器自動管理 | 需呼叫 @Remove 方法主動移除 |
| 併發存取 | 多執行緒安全 | 單執行緒存取,容器序列化 |
| 被動化/活化 | 不支援 | 支援 @PrePassivate/@PostActivate |
計數器介面與實作
@Remote
public interface Counter {
int add(int i);
int getNumber();
@Remove void clean(); // 標記移除方法
}
@Stateful
public class CounterBean implements Counter {
private int number = 0;
public int add(int i) { return number += i; }
public int getNumber() { return number; }
@Remove
public void clean() { System.out.println("Bean 已移除"); }
}
Client 測試驗證生命週期
Counter counter = (Counter) ctx.lookup(Counter.class.getName());
counter.add(10); // 10
Counter counter2 = (Counter) ctx.lookup(Counter.class.getName());
counter2.add(10); // 10,新實例獨立狀態
counter2.clean(); // 主動移除
counter2.getNumber(); // 拋出 NoSuchObjectException
交易支援示範
@TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
public int getNumber() { return number; }
最佳實踐
- 僅在真正需要會話狀態(購物車、精靈式流程)時使用
- 必須提供 @Remove 方法避免記憶體洩漏
- 大量併發場景評估被動化儲存開銷
- 叢集環境需配置 Session 複寫(replication)