首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

EJB 3 開發指南(4):Session Bean 生命週期回呼註解完整解析

     編輯:Java 相關知識

Session Bean 生命週期由容器管理,EJB 3 提供四個標準回呼註解 (@PostConstruct、@PreDestroy、@PostActivate、@PrePassivate) 配合 @Resource 注入 SessionContext,讓開發者在關鍵時間點執行資源初始化、清理、鈍化/活化邏輯。本文完整示範各註解觸發時機與實作範例。

一、四大生命週期回呼註解

註解觸發時機適用 Bean 類型典型用途
@PostConstruct建構子執行後、依賴注入完成後 Stateless、Stateful、Singleton資源初始化:資料庫連線、快取載入、執行緒池建立
@PreDestroy容器銷毀 Bean 實例前 Stateless、Stateful、Singleton資源釋放:關閉連線、儲存狀態、關閉執行緒池
@PrePassivateStateful Bean 被鈍化 (序列化至硬碟) 前Stateful釋放非序列化資源:JDBC Connection、Socket、開啟檔案
@PostActivateStateful Bean 被活化 (從硬碟還原) 後Stateful重建資源:重新取得連線、恢復暫存狀態

二、完整程式碼範例:購物車 Stateful Bean

package service;

import java.util.ArrayList;
import java.util.List;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import javax.annotation.Resource;
import javax.ejb.PostActivate;
import javax.ejb.PrePassivate;
import javax.ejb.SessionContext;
import javax.ejb.Stateful;

@Stateful
public class ShoppingCartBean implements ShoppingCart {

    private List<String> shoppingCart = new ArrayList<String>();
    @Resource
    private SessionContext sessionContext;

    public ShoppingCartBean() {
        System.out.println("constructor: " + sessionContext);  // SessionContext 尚未注入
    }

    @PostConstruct
    public void init() {
        System.out.println("PostConstruct: " + sessionContext.getInvokedBusinessInterface());
        // 初始化資源:如載入用戶偏好設定
    }

    @PreDestroy
    public void destroy() {
        System.out.println("PreDestroy");
        // 釋放資源
    }

    @PrePassivate
    public void passivate() {
        System.out.println("PrePassivate");
        // shoppingCart 可序列化,無需特殊處理
        // 若持有非序列化資源 (Connection),此處必須釋放
    }

    @PostActivate
    public void activate() {
        System.out.println("PostActivate");
        // 重建非序列化資源
    }

    @Override
    public void addCommodity(String value) {
        shoppingCart.add(value);
    }

    @Override
    public List<String> getCommodity() {
        return shoppingCart;
    }
}

三、SessionContext 實用方法

方法用途
getBusinessObject(Class)取得 Bean 的業務介面代理 (用於自我呼叫)
getCallerPrincipal()取得呼叫者身分 (安全檢查)
isCallerInRole(String)檢查呼叫者角色
setRollbackOnly()標記交易回滾 (CMT)
getRollbackOnly()檢查交易是否已標記回滾
getTimerService()取得 TimerService (排程)
getInvokedBusinessInterface()取得正在執行的業務介面 Class

四、生命週期流程圖

Stateless Bean

實例化 → @PostConstruct → 服務就緒 → (處理請求) → @PreDestroy → 銷毀

Stateful Bean

實例化 → @PostConstruct → 服務就緒
    │                              │
    │  閒置超過 timeout            │  客戶端移除/容器回收
    ▼                              ▼
@PrePassivate (鈍化)          @PreDestroy (銷毀)
    │                              │
    │  客戶端再次呼叫              │
    ▼                              │
@PostActivate (活化) ────────────┘
    │
    ▼
繼續服務

五、關鍵注意事項

  • 建構子中不可使用注入資源:@Resource 注入發生在建構子之後,@PostConstruct 之前
  • Stateless Bean 無鈍化/活化:@PrePassivate/@PostActivate 僅對 Stateful 生效
  • 例外處理:回呼方法拋出運行時異常會導致交易回滾 (CMT) 或實例銷毀
  • 併發安全:Stateful Bean 同一時間僅服務一個客戶端,無併發問題;Singleton 需自行處理併發 (@Lock)
  • 序列化要求:Stateful Bean 所有非 transient 欄位必須可序列化,否則鈍化失敗

六、實戰模式:資源管理範本

@Stateful
public class ResourceManagedBean implements ResourceManaged {

    @Resource private DataSource dataSource;
    private Connection conn;  // 非序列化,不可鈍化

    @PostConstruct
    public void init() {
        try { conn = dataSource.getConnection(); }
        catch (SQLException e) { throw new EJBException(e); }
    }

    @PrePassivate
    public void passivate() {
        try { if (conn != null && !conn.isClosed()) conn.close(); }
        catch (SQLException e) { /* log */ }
        conn = null;
    }

    @PostActivate
    public void activate() {
        try { conn = dataSource.getConnection(); }
        catch (SQLException e) { throw new EJBException(e); }
    }

    @PreDestroy
    public void destroy() {
        try { if (conn != null && !conn.isClosed()) conn.close(); }
        catch (SQLException e) { /* log */ }
    }
    // 業務方法使用 conn...
}

七、Singleton Bean (EJB 3.1+) 补充

  • @Startup:應用啟動時立即初始化 (觸發 @PostConstruct)
  • @DependsOn:指定初始化順序依賴
  • @Lock(LockType.READ/WRITE):方法級併發控制
  • 同樣支援 @PostConstruct/@PreDestroy,無鈍化/活化
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved