ejb在java中的地位(java中ejb是什麼)

本文目錄一覽:

關於java的持久化,ejb和hibernate哪個應用的廣些?

應該說EJB中對於數據的持久化方面和hibernate的功能是一致的,但兩者沒法從全局上比較,兩者的適合範圍和功能區別實在太大

一段時間以來,EJB、Hibernate、Spring的恩怨情仇,是J2EE的熱門話題。EJB VS Hibernate、EJB VS Spring這樣的議題隨處可在。這篇文章,筆者試圖通過對技術發展史的回顧,對source的剖析、對比,深入挖掘這些技術出現的初衷、缺陷、走向。

前言

我強調EJB、Hibernate、Spring的恩怨情仇,同時也必須說明,我一向反感你說我怎麼侵入、你說我怎麼依賴式的EJB VS Hibernate、EJB VS Spring的討論,因為這種行為本身就是沒有意義的、錯誤的。我提倡從正確的技術對比和理性的技術批判中受益。對比,我們需要找准對比點;批判,我們需要從source、spec、application context中分析、批判。

從EJB說起

2.1 EJB幾種Bean類型的引入順序

EJB1.0,有兩種Bean類型:SessionBean、EntityBean。

EJB2.0,引入CMP EntityBean、引入Message-Driven Bean、引入Local接口。

2.2 Entity Bean和O/R Mapping的微妙關係

我想對O/R Mapping、O/R Mapping Engine做一個簡要的說明。

O/R Mapping,以對象視圖(Object View)來看待DB Record,對象操作能夠通明地映射成DB Record操作。

O/R Mapping Engine,就是使得O/R Mapping成為可能的具體實現手法。

從我們的定義來看,使用BMP EntityBean意味着你自己在實施一個非常簡單的O/R Mapping ,你自己在為能夠以對象視圖和DB交互做出努力。而為了支持CMP EntityBean,EJB Server提供商會為你提供O/R Mapping 能力。而且,事實的確是這樣,任何支持CMP EntityBean的EJB Server都需要提供一個Persistence(O/R Mapping) Engine,譬如JBOSS的JAWS(Just Another Web Store)。

至於,Hibernate、IBATIS等,雖然,也叫做O/R Mapping Tool,但是它們的意義已經遠遠超過了CMP EntityBean O/R Mapping Engine這樣的Tool。下面會有詳細的分析。

2.3 EJB-1.0

EJB1.0是分布式組件架構,包括SessionBean和EntityBean。它引入了很多非常前衛的技術、概念。主要包括分布式組件、容器、DB操作的對象試圖。

EJB1.0,可能Expert Group設想的EJB的應用場景是大規模分布式的系統。所以,SessionBean、EntityBean尚沒有引入Local接口。 client-SessionBean、client-EntityBean、SessionBean-SessionBean、SessionBean-EntityBean等等都是remote的。

EJB1.0,將容器這個概念引入EJB,意義重大。這裡我想順便澄清一個問題:容器是什麼?我的觀點:容器只是一個概念、一種架構。就拿EJB Server來說,Server試圖為Bean提供分布式、事務、安全等基礎設施,那麼就必須有一個凌駕於Bean之上的Layer或者說warp,這樣才能夠從高層攔截Bean調用,進行一些額外操作。這樣的架構就叫做容器架構,這個概念當然不是自EJB才有的。至於怎樣實現,方法各異。

事實上,以個人的觀點,容器架構的核心,不在於從高層“掌握”Beans(Objects),而在於採用怎樣的技術來實現Bean(Object)調用的攔截。無疑,EJB Servers和Spring的實現手法是不同的。下面會詳細討論這個問題。

EJB1.0為DB操作提供了對象試圖。Expert Group當初是怎樣定位EntityBean的?無疑,1.0中的EntityBean,也就是2.0以後的BMP EntityBean,定位是Domain Object(我不知道當時有沒有這個概念,只是它們的思想是非常一致)。它的fields直接映射DB Table Schema,member functions就是對Table Record的操作。Client-EntityBean、SessionBean-EntityBean等就可以直接和數據庫交互了。

有人跟我說EJB1.0基於Catalysis方法學,SessionBean對應Role,EntityBean對應Domain Object。到目前為止,我對這種說法,持保留態度,因為EJB Spec中,我絲毫沒有這種說法的痕迹。

2.4 EJB-2.X

無疑,EJB1.X的設計存在重大的缺陷。2.0增加的特性包括Local接口、CMP EntityBean,它們是對1.x缺陷的重大更正。

首先,事實上沒有多少Expert Group想象中的大規模分布式應用。我們從兩個方面來說:(1)通過Remote方式使用 EntityBean引起嚴重的性能問題,很有必要提供Local接口。(2)訪問SessionBean的WebApplication和SessionBean部署在同一服務器上的情況非常普遍,所以提供SessionBean的Local接口,也是必然的事情。2.X之後,最常用的一個Pattern就是使用SessionBean Façade通過Local的形式訪問EntityBean。而且,即使應用規模大到連SessionBean和EntityBean都需要部署到不同的Server,也沒有關係,因為EJB2.X同樣支持Remote接口。

其次,EJB2.0引入CMP EntityBean。CMP EntityBean解決了EntityBean持久化表示和JDBC分離的問題,同時大大簡化了EntityBean的開發、提高了性能。但是,我不得不說,CMP EntityBean將EJB1.X的Domain Model理念完全衝掉了,因為CMP EntityBean是不能包含任何Domain Logic的。BMP EntityBean似乎就是Matrin所說的DomainObject,而CMP EntityBean在典型的SessionBean-EntityBean這樣的應用場景下,似乎就是Martin所說的Transaction Script中的AnaemicDomainObject。

順便說一下,我個人是不同意Martin的RichDomainObject的說法。因為,在數據應用系統中,Martin提到的相對於Transacton Script中AnaemicDomainObject的RichDomainModel往往沒有反映現實世界。一個Bank Account反映到現實世界,就是賬本中的一條記錄,它沒有自發的動作,譬如withdraw。它和Person不同,Person可以有say(String words)這樣的自發動作。Account的withdraw應該放到AccountManager中,由AccountManger來操作Account。不是說OO中的Object都需要有動作,現實世界中,本來就有靜態的、沒有自發動作的事物,譬如一個賬本、一個帳號、一個資料庫。雖然,不可否認,Rich Domain Model(對比AnaemicDomainObject說的)能夠帶來不少的好處(什麼樣的好處,你看看Martin的《Domain Logic and SQL》,就知道了)。

三、我理解的Hibernate

本來,本文的題目叫做《EJB、Spring:剖析、批判和展望》,因為我覺的Hibernate和EJB、Spring不是一個層次的東西,雖然,這個道理很淺顯,但是為什麼那麼多人還拿Hibernate來攻擊EJB,來攻擊EntityBean?EntityBean是值得狠狠攻擊的,但是你用錯了槍。

我上面提到,支持CMP EntityBean的EJB Implements都有一個Persistence Engine,也就是O/R Mapping Engine。CMP O/R Mapping Engine用來做什麼的?它通過分析CMP Abastract Schema、分析EJBQL、分析Bean狀態等行為,生成SQL,然後和DB 進行交互。

而在我眼裡,Hibernate不是”O/R Mapping Tool”這幾個字能概括的了。我說Hibernate是一款獨當一面的輕量級翻譯中間件,是Layer,和CMP EntityBean O/R Mapping Engine不是一個層次的東西了。

Application——-CMP EntityBean Operation——–DB

|

(O/R Mapping Engine)

———————-

|—HQL、Criteria Query

Application—— Hibernate —— |—POJO/PO Operation——— DB

|—and so on

通過上面的兩個圖,你看出區別來了嗎?

EntityBean應用,不知道O/R Mapping Engine的存在,只需要使用EntityBean來完成交互。

而在Hibernate應用中,Application是直接使用Hibernate的。也就是說,它是直接使用O/R Mapping Engine的。

在這裡,我建議你停下來,想想EntityBean是不是應該對應Hibernate中的PO/POJO?舉個例子,你修改PO後,是不是需要sessionObj.update(po)來更新,這個sessionObj.update(po)是不是表示你直接使用Hibernate的Persitence Engine?是的。而在EntityBean中,你修改EntityBean後,你需要其它的行為來使得EntityBean的變化同步到DB嗎?不需要。因為,EJB Container攔截你的調用,在你更改Bean的field之前、之後,container會調用load/store方法的(當然,在BMP/CMP EntityBean中,情況是不同的,BMP EntityBean調用programmer自己用JDBC編寫的load/store等方法,而CMP EntityBean,使用CMP Peristence Engine來做這個工作)。這樣,就隱式的持久化數據了。不需要,你像Hibernate那樣調用session.update這樣的語句。EntityBean這種同步方式是對它性能差的重要原因之一。值得注意的是,EJB Implements對於EntityBean同步並不完全是我上面描述的那樣,同步的頻率和事務、特定的implements是緊密相關的。

總的來說,CMP EntityBean O/R Mapping Engine是為靜態的、功能固定的EntityBean的O/R Mapping提供支持而開發的。而Hibernate擔任的是一個Layer的作用。

四、Spring不是神話

Rd Johnson聰明在哪裡?聰明在,他堅持了自己的實踐,而不是隨大流。Rd Johnson認識到90%的應用不需要分布式、不需要J2EE中那些重量級的技術,譬如JNDI,他就動手為EJB脫去Remote這層皮、將大多數應用中不必要的技術隔離、改造。從適用範圍上來說,Spring對EJB做了90%的補充。

個人看法:Spring的哲學在於,framework針對最常見、最簡單的應用場景而設計,等到需要特殊技術的時候,再想辦法解決問題。這樣,在絕大多數沒有特殊要求的應用中,Spring就顯示出優勢來了。下面,我們會做詳細的講解。

4.1 Spring“無侵入性“是謊言,但是有資格笑”百步之外的EJB”

“無侵入性”是Spring標榜的特性。但是,我想說,Spring的“無侵入”是謊言,隨着應用的深入,“無侵入”對什麼framework來說,都是個神化。

什麼就叫“無侵入性”?部署到Spring中的Object不需要強制任何實現接口就可以說Spring是“無侵入性”的?我覺的,這是大錯特錯。如果你非要說,Spring的確不需要像EJB那樣強制實現一些接口,那麼我只能告訴你:

(1)Spring設想的Object的應用場景是從最簡單的出發。所以,它沒有,為了一些預料中要使用的特性而強制Object實現一些特定的接口。但是,事實上,在Spring中,如果你的應用場景稍微深入一點,那麼你就和和Spring綁定了。

(2)Spring管理的Object,從某種意義上說是沒有狀態的。

針對第一點,我舉兩個個例子。(1)EJB內部方法的調用,會導致基礎設施不會起作用。但是Bean接口(SessionBean、EntityBean、MessageDrivenBean)中都有可以使Bean獲得自己Context的支持,譬如:SessionBean的setSessionContext(SessionContext ctx) 等等,容器部署Bean的時候會通過它給每個Bean設置一個上下文。而EJBContext中,有EJBObject getEJBObject這樣的函數,可以使得Bean獲得自身的EJBObject,這樣通過EJBObject來調用Bean自己的函數,基礎設施就會起作用了。而Spring中,如果,一個Object的函數需要調用自己的其它函數,而又希望譬如安全檢查、事務等等Aspect起作用?那麼Spring,怎麼做?你需要設置Bean的exposeProxy屬性。

ExposeProxy: whether the current proxy should be exposed in a ThreadLocal so that it can be accessed by the target. (It’s available via the MethodInvocation without the need for a ThreadLocal.) If a target needs to obtain the proxy and exposeProxy is true, the target can use the AopContext.currentProxy() method.

所以,當你需要上面說的內部調用需要基礎設施起作用的特性,不管在EJB還是Spring肯定需要和特定框架綁定的。為什麼說,Spring五十步笑百步?因為,我上面提到,Spring在Object很簡單的情況下,是可以任意部署的、復用的。而EJB卻不管你需不需要,開始就設想你需要的。同樣,Spring中的BeanFactoryAware、BeanNameAware等等接口也都說明了一點:Spring將特性從Object剝離,從而,盡量降低它的依賴性。只有當你的Object複雜的時候,framework才會侵入你的Object。

針對,第二點,我想着重談一下。為什麼說,從某種意義上說Spring中部署的對象是沒有狀態的?我們知道,Spring支持兩種Object:Singleton和Prototype。Spring Spec中,認為,Singleton可以稱為stateless的,Prototype可以稱為是statefule的。而在EJB的世界中,StatefuleSessionBean和EntityBean也稱作是stateful的。那麼,它們的stateful分別意味着什麼?它們為什麼在依賴性方面有那麼大的區別?為什麼Spring中的Object不需要實現特定接口,而EJB需要?先來,看看EJB的SessionBean接口:

void ejbActivate()

The activate method is called when the instance is activated from its

“passive” state.

void ejbPassivate()

The passivate method is called before the instance enters the

“passive” state.

void ejbRemove()

A container invokes this method before it ends the life of the

session object.

void setSessionContext(SessionContext ctx)

Set the associated session context.

其中的setSessionContext我上面說過。看ejbActivate()、ejbPassive(),為什麼會有這兩個函數?而Spring不需要實現有同樣函數的接口?這是EJB和Spring的對象管理機制的不同造成。EJB implements一般來說,為了復用Bean,會採用一級Cache加上一級InstancePool(StatelessSessionBean是不需要Cache的),從而支持將StatefulSessionBean持久化到磁盤,支持EntityBean的Bean Instance(注意這個Bean Instance和client得到的EntityBean是不同的,它沒有和任何的DB Record關聯)的復用,這就導致了ejbAcrivate、ejbPassivate等的引入。但是,Spring沒有採用這樣管理機制,它只有Singleton/Prototype。而Prototype雖然也可以說成是Statefule的,但是它不會在不同的client中復用Object Instance,而是每一個client一個對象,哪怕一萬個client,那麼就產生一萬個Instance,而在EJB中,可能使用100 Instance來服務,將not active的Bean持久化到磁盤,復用Bean Instance。還請注意,這裡我不是說EJB中的StatefuleSessionBean好,事實上我發現,一般來說,當並發量很大時,採用節約內存而持久化Bean到磁盤這種策略,I/O瓶頸引起的問題更為嚴重。

再看,ejbRemove,這個沒什麼多說的,Spring中你可以選擇實現InitializingBean、DisposableBean接口,但是Spring推薦不要這樣做,可以寫普通的init成員函數,然後在配置文件中指明init-method、destroy-method屬性,這樣避免和Spring框架的綁定。

總的來說,Spring從對象最基本的引用場景出發,當需要複雜特性的時候,才會採用特殊機制來解決問題,也就是在這時,才會使應用綁定到Spring中。所以,它的侵入性比較低,但是不是“無侵入性”,不是你想的那麼美好,當然,也沒有“絕對無侵入“的framework。

4.2 我覺的Spring IOC的設計思路不夠完美

Spring的IOC被一些人當作多麼神奇的東西。

EJB具有Spring中所說的那種IOC的能力嗎?答案是肯定的。EJB中的EJB引用、資源引用、環境屬性都可以說是IOC,不是嗎?然而,Spring和EJB的IOC不同在哪裡?

Spring注入的特色:主要考慮Local Object的查找,這個時候不需要任何的協議(譬如JNDI),當你需要注入Remote Object的時候,採用RMI協議或者使用第三方Tool(譬如Hessian)。

EJB的特色:無論你的Bean-Bean是否部署在同一台機器上、Client-Bean是否在同一台機器上,肯定需要通過JNDI來查詢Bean,只是,如果是它們在同一台機器上的時候,你使用Local接口,這樣使得調用變為Local調用,從而提升性能。EJB它從出生時起,就定位為分布式組件架構,一頭栽進“distributed”不容易出來了。這個可能就叫“尾大不掉”吧。

這一切的不同,只能說,它們的定位不同。一個更關注Local、一個更關注Remote。Spring仍然堅持它的哲學,從最基本的、大多數的場景考慮起,到特殊需要的時候,再想辦法來解決問題。它試圖找到J2EE開發和系統能力的均衡點。

可以說,Spring的做法,更加合情合理。但是,我也相信,Spring在”只是為Remote注入提供簡單的支持“這一點上有點矯枉過正。我覺的,它可以做的更好,譬如通過作為J2EE標準的JNDI來封裝Local、Remote查找。

目前,Spring不怎麼關心Remote Object注入,對於需要Remote注入的情況,只提供簡單的支持,而且還需要針對expert單獨寫配置信息。在這裡,EJB3.0的做法,我覺的,是目前,最方便、最理智、也是最有前途的。EJB3.0通過@remote、@local就可以讓EJB Server做不同的部署。

Spring導出遠程對象。

AccountService

example.AccountService

1199

Spring中注入Remote是怎樣做的?

rmi://HOST:1199/AccountService

example.AccountService

看了,這段代碼,你就知道了。

這種方法非常的輕量級,從本質上來說,這種方法和JNDI沒有任何的不同,這種方法,也需要一個NamingService,還記得RMI編程中,運行服務端的時候,首先運行rmiregistry,這個實際上就是非常簡單的NamingService。看來,Rd Johnson對JNDI真是深惡痛絕啊。怎麼也不願意用JNDI。Spring這種方法,也許沒有JNDI那樣重量級,但是很顯然它不能支持工業級分布系統,J2EE發展到今天,JNDI已經成為最核心的技術,它不是簡單的Object Naming Service,它提供標準接口來定位用戶、微機、網絡、對象、服務器等等。它已經廣泛而深入的進入J2EE技術的各個領域、成為J2EE系統的紐帶。

舉個很簡單的例子:我需要在Spring應用中動態獲取Remote Object,我該怎麼做?我需要無縫使用LDAP,我該怎麼做?答案是,Spring不能幫到你什麼。

那麼我就想,Spring為什麼不使用JNDI來封裝Local、Remote查找兩種協議?從而,使用J2EE標準來實現無縫

EJB是java方向必學的嗎

EJB是用來做分布式布署時用到。一般像電信、銀行等大型系統用到。小系統用SSH就夠了。你應該是剛學JAVA,先從基礎搞起吧,把一些基本的協議掌握,基礎知識搞紮實。夠用了。到一定程度,你再學EJB之類的也就有基礎了。現在你學了也白學。一是用不到,二是你也不會學到很懂。實話。

EJB 與 JAVA BEAN 的區別?

Java Bean 是可復用的組件,對 Java Bean 並沒有嚴格的規範,理論上

講,任何一個 Java 類都可以是一個 Bean 。但通常情況下,由於 Java Bean

是被容器所創建(如 Tomcat) 的,所以 Java Bean 應具有一個無參的構造器

,另外,通常 Java Bean 還要實現 Serializable 接口用於實現 Bean 的持久

性。 Java Bean 實際上相當於微軟 COM 模型中的本地進程內 COM 組件,它是

不能被跨進程訪問的。 Enterprise Java Bean 相當於 DCOM ,即分布式組件

。它是基於 Java 的遠程方法調用( RMI )技術的,所以 EJB 可以被遠程訪

問(跨進程、跨計算機)。但 EJB 必須被布署在諸如 Webspere 、 WebLogic

這樣的容器中, EJB 客戶從不直接訪問真正的 EJB 組件,而是通過其容器訪

問。 EJB 容器是 EJB 組件的代理, EJB 組件由容器所創建和管理。客戶通過

容器來訪問真正的 EJB 組件。

EJB與java三大框架的區別是什麼?

EJB 可以簡單理解為三層 實體、業務 和 數據庫

而三大框架 struts 是對頁面展示的擴展 和ejb沒關係

hibernate 是對數據庫的改變 把關係數據庫變成對象數據庫

spring是對項目的管理 降低耦合性的

框架只是對某一塊的規範 和擴展

EJB是一個項目的層次的搭建

比如 頁面 、業務、實體、數據庫

而要擴展頁面的展示 有個struts的框架

要把數據庫搞的靈活些(用hibernate如果從oracle換到mysql 就換個驅動就成 不用怎麼改代碼)用hibernate

原創文章,作者:小藍,如若轉載,請註明出處:https://www.506064.com/zh-hant/n/300830.html

(0)
打賞 微信掃一掃 微信掃一掃 支付寶掃一掃 支付寶掃一掃
小藍的頭像小藍
上一篇 2024-12-29 14:18
下一篇 2024-12-29 14:18

相關推薦

  • Java JsonPath 效率優化指南

    本篇文章將深入探討Java JsonPath的效率問題,並提供一些優化方案。 一、JsonPath 簡介 JsonPath是一個可用於從JSON數據中獲取信息的庫。它提供了一種DS…

    編程 2025-04-29
  • java client.getacsresponse 編譯報錯解決方法

    java client.getacsresponse 編譯報錯是Java編程過程中常見的錯誤,常見的原因是代碼的語法錯誤、類庫依賴問題和編譯環境的配置問題。下面將從多個方面進行分析…

    編程 2025-04-29
  • Java Bean加載過程

    Java Bean加載過程涉及到類加載器、反射機制和Java虛擬機的執行過程。在本文中,將從這三個方面詳細闡述Java Bean加載的過程。 一、類加載器 類加載器是Java虛擬機…

    編程 2025-04-29
  • Java騰訊雲音視頻對接

    本文旨在從多個方面詳細闡述Java騰訊雲音視頻對接,提供完整的代碼示例。 一、騰訊雲音視頻介紹 騰訊雲音視頻服務(Cloud Tencent Real-Time Communica…

    編程 2025-04-29
  • Java Milvus SearchParam withoutFields用法介紹

    本文將詳細介紹Java Milvus SearchParam withoutFields的相關知識和用法。 一、什麼是Java Milvus SearchParam without…

    編程 2025-04-29
  • Java 8中某一周的周一

    Java 8是Java語言中的一個版本,於2014年3月18日發布。本文將從多個方面對Java 8中某一周的周一進行詳細的闡述。 一、數組處理 Java 8新特性之一是Stream…

    編程 2025-04-29
  • Java判斷字符串是否存在多個

    本文將從以下幾個方面詳細闡述如何使用Java判斷一個字符串中是否存在多個指定字符: 一、字符串遍歷 字符串是Java編程中非常重要的一種數據類型。要判斷字符串中是否存在多個指定字符…

    編程 2025-04-29
  • VSCode為什麼無法運行Java

    解答:VSCode無法運行Java是因為默認情況下,VSCode並沒有集成Java運行環境,需要手動添加Java運行環境或安裝相關插件才能實現Java代碼的編寫、調試和運行。 一、…

    編程 2025-04-29
  • Java任務下發回滾系統的設計與實現

    本文將介紹一個Java任務下發回滾系統的設計與實現。該系統可以用於執行複雜的任務,包括可回滾的任務,及時恢復任務失敗前的狀態。系統使用Java語言進行開發,可以支持多種類型的任務。…

    編程 2025-04-29
  • Java 8 Group By 會影響排序嗎?

    是的,Java 8中的Group By會對排序產生影響。本文將從多個方面探討Group By對排序的影響。 一、Group By的概述 Group By是SQL中的一種常見操作,它…

    編程 2025-04-29

發表回復

登錄後才能評論