企業級JavaBean(Enterprise JavaBean, EJB,或稱Jakarta Enterprise Beans)是一個用來構築企業級應用的伺服器端可被管理組件。

Java企業版API(Java Enterprise Edition)中提供了對EJB的規範。EJB是一個封裝有某個應用程式之業務邏輯伺服器端組件。EJB最早於1997年由IBM提出,旋即被太陽電腦採用並形成標準(EJB 1.0 和EJB 1.1)。其後在Java社區行程(Java Community Process)支援下陸續有一些JSR被制訂來定義新的EJB標準,分別是JSR 19 (EJB 2.0), JSR 153 (EJB 2.1) 以及最新的JSR 220 (EJB 3.0)。

EJB規範的目的在於為企業及應用開發人員實現後台業務提供一個標準方式,從而解決一些此前總是在作業過程中總是重複發生的問題。EJB以一個標準方式自動處理了諸如數據持久化,事務整合,安全對策等不同應用的共有問題,使得軟件開發人員可以專注於程式的特定需求而不再飽受那些非業務元素的困擾。

據此,EJB規範明確了一個應用伺服器應當支援的中間管理細目,包括:

  • 數據持久化
  • 事務處理
  • 並行控制
  • 基於JMS的事件驅動
  • 基於JNDI的名字和空間管理
  • 基於JCEJAAS的安全管理
  • 應用伺服器端的軟件組件部署
  • 使用RMI-IIOP協定的遠端程序呼叫
  • 將業務方法暴露為Web服務

此外,EJB定義文件還指定了EJB容器和各EJB的角色定位,以及如何將EJB部署至EJB容器當中。

EJB的架構

歷史

從擁抱到拋棄

由於IBMSun Microsystems等EJB提倡者力推其前景,起初一些大公司紛紛採用EJB部署他們的系統。然而隨後各種問題便接踵而至,對EJB的惡評短時間內激增。對於初學者,EJB的API顯得太過困難;對於許多程式設計師來說,書寫那些必須投擲特定異常的介面並將bean類作為抽象類實現的做法既不直觀也不正常。當然,EJB所被賦予的使命,如對象關係對映和事務管理確實有其天然複雜性,但其API之複雜還是令開發人員們覺得望而卻步,一些人開始懷疑EJB除了引入了複雜的實現手段以外似乎並未帶來什麼實際好處。

另外,實際運用中被發現,如果使用EJB來封裝業務邏輯會帶來效能上的下降。這是因為,最早的EJB規範只允許客戶端通過特定協定(如CORBA)進行遠端方法呼叫來呼叫,即使大部分實際應用根本就不需要分散式計算。直到EJB 2.0才引入了本地介面,以支援可以開發不通過網絡就能直接本地呼叫的EJB系統。

儘管如此,EJB的廣泛普及仍然為其複雜度所制約。儘管已經有一些高質素的整合開發工具可以協助開發人員通過自動編碼解決一部分重複作業,但這並不能降低學習此項技術的難度。另一方面,「草根階層」的編程愛好者們發起了一場旨在使用 「輕量級」技術以代替複雜的EJB的運動。這些技術包括Hibernate(用於提供數據持久化和對象-關係對映)及Spring框架(用於封裝業務邏輯)。儘管它們不像EJB那樣有巨頭支援,但其在庶民間卻更加流行,並且也被一些對EJB深感失望的企業所採用。

重生

EJB規範起初的一個主要價值—對分散式應用進行事務管理—在隨後的實踐中被一致認為幾乎沒能派上用場。對於企業級應用來說,Spring和Hibernate等簡化框架更加實用。因此,EJB 3.0規範(JSR 220)為了迎合這個趨勢相比於其前輩進行了一次激進的大跳躍。受到Spring 影響,EJB 3.0也使用所謂的「傳統簡單Java對象(POJO)」;同時,支援依賴注入來簡化全異系統的整合與組態。Hibernate的創始人Gavin King參與了這一新版規範的制訂,並對EJB大加提倡。Hibernate的許多特性也被引入到Java持久化API當中,從而取代原來的實體bean。EJB 3.0規範大幅採用Java註解(annotation)來對代碼進行元數據修飾,從而消減了此前EJB編程的冗雜性。

相應地,EJB 3.0幾乎成為了一個全新的API,與此前的數版可謂毫無相似度可言。

EJB種類

EJB容器可以接受三類EJB

  • 對談Bean(Session Beans)
    • 無狀態對談Bean(Stateless Session Beans)
    • 有狀態對談Bean(Stateful Session Beans)
  • 實體Bean(Entity Beans)
  • 訊息驅動Bean(Message Driven Beans ,MDBs)

無狀態對談Bean是一類不包含狀態資訊的分散式對象,允許來自數個客戶端的並行存取。實例變數的內容在前後數次呼出中不被保留(確切地說是不保證保留)。由於不必控制與用戶間的對話資訊而減少了開銷,無狀態對談Bean不像有狀態對談Bean那樣具有資源集約性。舉例來說,一個傳送郵件的EJB就可被設計為一個無狀態對談Bean。在整個對談期,用戶只向伺服器提交一個動作:傳送指定郵件到指定地址。(稱為開關行為)

有狀態對談Bean是包含狀態的分散式對象,即是說,貫穿整個對談它們都要保有客戶端資訊。舉例而言,在一個網上商店進行實施結賬很可能就需要一個有狀態對談Bean,因為結賬是一個多步動作,伺服器端必須可以隨時了解到用戶已經進行到了哪一步。此外,儘管有狀態對談Bean的狀態資訊可被保持,但始終只能是由同一個用戶來訪問之。

實體Bean是含有持久化狀態的分散式對象。這個持久化狀態的管理既可以交給Bean自身(Bean-Managed Persistence,BMP),也可以託付於外部機制(Container-Managed Persistence,CMP)。

訊息驅動Bean是支援非同步行為的分散式對象。它們並不對請求進行當即響應。比方說,某網站用戶點擊「請通知我更新資訊」按鈕,將會觸發某個MDB將這名用戶加入到資料庫的希望獲得更新資訊用戶列表中。這個動作就是一個非同步的訊息驅動過程,因為用戶不必等待當時會返回某個結果。MDB的訊息源來自Java訊息服務(JMS)提供的訊息佇列或訊息主題。自EJB 2.0規範起,JMS被加入進來以允許在容器內部實施事件驅動處理。與其他EJB不同,MDB不存在一個用戶視圖(如需要用戶參照的遠端介面),用戶也不能通過資源定位獲得一個MDB實例。MDB只在後台監聽訊息源並實施自動處理。

除了上述以外,目前還有一些EJB處於設想階段,如JSR 86提出了用於在Java EE應用中整合多媒體對象的媒體Bean(Enterprise Media Beans)。

EJB實行

EJB部署於應用伺服器端的EJB容器中。規範給定了EJB與EJB容器之間,以及用戶代碼與EJB/EJB容器之間的互動方式。對於Java EE API,javax.ejb包定義了EJB類,javax.ejb.spi包定義了EJB容器應當實現的各個介面。

在EJB 2.1和以前的版本中,每個EJB都由一個類和兩個介面組成。EJB容器負責建立這個類別的實例,介面則供客戶端呼叫。

兩個介面分別被稱為Home介面和組件介面,負責提供各個EJB遠端方法聲明。這些EJB遠端方法可分成兩組:

  • 類別方法:由Home介面提供。與特定實例無關,僅負責一些公共內容,比如建立一個新的EJB實例(create方法),或尋找一個已經存在的EJB實例(find方法)等等。
  • 介面方法:由組件介面提供的針對特定實例的業務方法。

EJB容器將為這些介面提供對應的實現類以充當客戶遠端代理,當客戶端呼叫這個生成的代理類的某個方法時,代理類內部會將此呼叫的方法和參數封裝成一個訊息傳送給伺服器。伺服器收到訊息後在轉發給真實的EJB實例,後者負責執行真正的業務邏輯。

遠端通訊

EJB規範要求EJB容器能夠支援基於RMI-IIOP的EJB訪問。EJB既可被任何CORBA應用訪問,也能提供Web服務。

事務

EJB容器必須支援符合ACID(原子性/一致性/獨立性/永續性)特性的容器級事務管理,以及bean內部事務管理。容器級事務需在部署描述符中(EJB應用的設定檔)進行聲明。

事件

EJB使用JMS向客戶對象傳送訊息,客戶則可以非同步地接受這些訊息。MDB則接受來自客戶端的訊息。

命名和目錄服務

EJB客戶端使用JNDI或CORBA名字服務定位Home介面實現 對象。通過此Home介面,用戶還可以尋找,建立或刪除實體對象。

安全

EJB容器對客戶端的訪問權限負責。

部署EJB

EJB規範還定義了一個跨平台的統一部署機制。部署描述符中定義了關於EJB應用的一切相關內容。檔名通常為ejb-jar.xml。

部署描述符是一個XML文件,負責為該EJB應用中的每一個EJB定義入口。部署描述符的主要內容包括:

  • Home介面名
  • Bean的Java類別名
  • Home介面的Java介面名
  • 組件介面的Java介面名
  • 持久化儲存(針對實體Bean)
  • 安全策略和角色分配

通常EJB容器提供者還定義了一些額外的XML或其他格式描述檔案來強化其容器的功能。他們還同時提供這些描述檔案的解讀工具類和對Home介面的自動實現類生成。

EJB3.0起開始廣泛使用Java註釋替代傳統的部署描述符ejb-jar.xml。但後者仍然有效。

版本變化

EJB 3.0

2006年5月2日發佈,JSR 220定義。

  • 全面採用Java註釋代替部署描述符。(後者仍可使用,並且具有更高優先級)
  • 把2.X版的EntityBean改為由JPA支援。

EJB 2.1

2003年11月24日發佈,JSR 153定義。

  • Web服務:可將無狀態對談bean暴露為Web服務;EJB可通過參照訪問Web服務。
  • EJB定時器服務:提供一種新的基於定時器的事件驅動方式。可供訊息驅動bean作為訊息源使用。
  • 增加了訊息目的地。
  • 進一步豐富了EJB查詢語言,支援ORDER BY, AVG, MIN, MAX, SUM, COUNT和MOD。
  • 使用XML schema代替DTD以定義部署描述符。

EJB 2.0

2001年8月22日發佈,JSR 19 定義。

  • 制定了構建物件導向商務應用的標準組建結構。
  • 支援構築使用不同開發工具所開發之組件的聯合應用部署。
  • 在多線程,連接池,事務管理等方面對用戶透明化。
  • 使符合「一次寫成,多次執行」的Java思想。
  • 關注企業級應用生命期間的開發,部署,執行等動作。
  • 定義了不同開發工具所需遵守的契約,以便其產品能夠在執行期互動。
  • 支援與現行系統相容,開發者可以擴充現有產品以使之支援EJB。
  • 與其他Java API相容。
  • 支援EJB與Java2平台企業版或者其他非Java應用程式之間的互操作性。
  • 支援與CORBA相容的RMI-IIOP。

EJB 1.1

1999年12月17日發佈。

  • 開始採用XML部署描述符,預設的JNDI上下文以及可支援IIOP的RMI。
  • 安全機制由角色(Role)驅動,而非方法。
  • 支援實體類,且必須在應用中實現。

EJB 1.0

1998年3月24日發佈。

  • 定義了EJB和EJB容器的作用,實現與互動。
  • 提供了最早的開發者與用戶視圖。

外部連結