|
EJB(2.X-3.0)、Hibernate、Spring:剖析、批判和展望
12/28/2004于珞珈山
一、 前言
我強(qiáng)調(diào)EJB、Hibernate、Spring的恩怨情仇,同時(shí)也必須說明,我一向反感你說我怎么侵入、你說我怎么依賴式的EJB VS Hibernate、EJB VS Spring的討論,因?yàn)檫@種行為本身就是沒有意義的、錯(cuò)誤的。我提倡從正確的技術(shù)對(duì)比和理性的技術(shù)批判中受益。對(duì)比,我們需要找準(zhǔn)對(duì)比點(diǎn);批判,我們需要從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的微妙關(guān)系
我想對(duì)O/R Mapping、O/R Mapping Engine做一個(gè)簡要的說明。
O/R Mapping,以對(duì)象視圖(Object View)來看待DB Record,對(duì)象操作能夠通明地映射成DB Record操作。
O/R Mapping Engine,就是使得O/R Mapping成為可能的具體實(shí)現(xiàn)手法。
從我們的定義來看,使用BMP EntityBean意味著你自己在實(shí)施一個(gè)非常簡單的O/R Mapping ,你自己在為能夠以對(duì)象視圖和DB交互做出努力。而為了支持CMP EntityBean,EJB Server提供商會(huì)為你提供O/R Mapping 能力。而且,事實(shí)的確是這樣,任何支持CMP EntityBean的EJB Server都需要提供一個(gè)Persistence(O/R Mapping) Engine,譬如JBOSS的JAWS(Just Another Web Store)。
至于,Hibernate、IBATIS等,雖然,也叫做O/R Mapping Tool,但是它們的意義已經(jīng)遠(yuǎn)遠(yuǎn)超過了CMP EntityBean O/R Mapping Engine這樣的Tool。下面會(huì)有詳細(xì)的分析。
2.3 EJB-1.0
EJB1.0是分布式組件架構(gòu),包括SessionBean和EntityBean。它引入了很多非常前衛(wèi)的技術(shù)、概念。主要包括分布式組件、容器、DB操作的對(duì)象試圖。
EJB1.0,可能Expert Group設(shè)想的EJB的應(yīng)用場景是大規(guī)模分布式的系統(tǒng)。所以,SessionBean、EntityBean尚沒有引入Local接口。 client->SessionBean、client->EntityBean、SessionBean->SessionBean、SessionBean->EntityBean等等都是remote的。
EJB1.0,將容器這個(gè)概念引入EJB,意義重大。這里我想順便澄清一個(gè)問題:容器是什么?我的觀點(diǎn):容器只是一個(gè)概念、一種架構(gòu)。就拿EJB Server來說,Server試圖為Bean提供分布式、事務(wù)、安全等基礎(chǔ)設(shè)施,那么就必須有一個(gè)凌駕于Bean之上的Layer或者說warp,這樣才能夠從高層攔截Bean調(diào)用,進(jìn)行一些額外操作。這樣的架構(gòu)就叫做容器架構(gòu),這個(gè)概念當(dāng)然不是自EJB才有的。至于怎樣實(shí)現(xiàn),方法各異。
EJB1.0為DB操作提供了對(duì)象試圖。Expert Group當(dāng)初是怎樣定位EntityBean的?無疑,1.0中的EntityBean,也就是2.0以后的BMP EntityBean,定位是Domain Object(我不知道當(dāng)時(shí)有沒有這個(gè)概念,只是它們的思想是非常一致)。它的fields直接映射DB Table Schema,member functions就是對(duì)Table Record的操作。Client->EntityBean、SessionBean->EntityBean等就可以直接和數(shù)據(jù)庫交互了。
有人跟我說EJB1.0基于Catalysis方法學(xué),SessionBean對(duì)應(yīng)Role,EntityBean對(duì)應(yīng)Domain Object。到目前為止,我對(duì)這種說法,持保留態(tài)度,因?yàn)?/span>EJB Spec中,我絲毫沒有這種說法的痕跡。
2.4 EJB-2.X
無疑,EJB1.X的設(shè)計(jì)存在重大的缺陷。2.0增加的特性包括Local接口、CMP EntityBean,它們是對(duì)1.x缺陷的重大更正。
首先,事實(shí)上沒有多少Expert Group想象中的大規(guī)模分布式應(yīng)用。我們從兩個(gè)方面來說:(1)通過Remote方式使用 EntityBean引起嚴(yán)重的性能問題,很有必要提供Local接口。(2)訪問SessionBean的WebApplication和SessionBean部署在同一服務(wù)器上的情況非常普遍,所以提供SessionBean的Local接口,也是必然的事情。2.X之后,最常用的一個(gè)Pattern就是使用SessionBean Façade通過Local的形式訪問EntityBean。而且,即使應(yīng)用規(guī)模大到連SessionBean和EntityBean都需要部署到不同的Server,也沒有關(guān)系,因?yàn)?/span>EJB2.X同樣支持Remote接口。
其次,EJB2.0引入CMP EntityBean。CMP EntityBean解決了EntityBean持久化表示和JDBC分離的問題,同時(shí)大大簡化了EntityBean的開發(fā)、提高了性能。但是,我不得不說,CMP EntityBean將EJB1.X的Domain Model理念完全沖掉了,因?yàn)?/span>CMP EntityBean是不能包含任何Domain Logic的。BMP EntityBean似乎就是Matrin所說的DomainObject,而CMP EntityBean在典型的SessionBean->EntityBean這樣的應(yīng)用場景下,似乎就是Martin所說的Transaction Script中的AnaemicDomainObject。
三、 我理解的Hibernate
本來,本文的題目叫做《EJB、Spring:剖析、批判和展望》,因?yàn)槲矣X的Hibernate和EJB、Spring不是一個(gè)層次的東西,雖然,這個(gè)道理很淺顯,但是為什么那么多人還拿Hibernate來攻擊EJB,來攻擊EntityBean?EntityBean是值得狠狠攻擊的,但是你用錯(cuò)了槍。
我上面提到,支持CMP EntityBean的EJB Implements都有一個(gè)Persistence Engine,也就是O/R Mapping Engine。CMP O/R Mapping Engine用來做什么的?它通過分析CMP Abastract Schema、分析EJBQL、分析Bean狀態(tài)等行為,生成SQL,然后和DB 進(jìn)行交互。
而在我眼里,Hibernate不是”O/R Mapping Tool”這幾個(gè)字能概括的了。我說Hibernate是一款獨(dú)當(dāng)一面的輕量級(jí)翻譯中間件,是Layer,和CMP EntityBean O/R Mapping Engine不是一個(gè)層次的東西了。
Application------->CMP EntityBean Operation-------->DB |
|
|
在這里,我建議你停下來,想想EntityBean是不是應(yīng)該對(duì)應(yīng)Hibernate中的PO/POJO?舉個(gè)例子,你修改PO后,有時(shí)是不是需要sessionObj.update(po)來更新(當(dāng)然,在非夸Session的情況下,不需要顯式的update的),這個(gè)sessionObj.update(po)是不是表示你直接使用Hibernate的Persitence Engine?是的。而在EntityBean中,你修改EntityBean后,你需要其它的行為來使得EntityBean的變化同步到DB嗎?不需要。因?yàn)椋?/span>EJB Container攔截你的調(diào)用,在你更改Bean的field之前、之后,container會(huì)調(diào)用load/store方法的(當(dāng)然,在BMP/CMP EntityBean中,情況是不同的,BMP EntityBean調(diào)用programmer自己用JDBC編寫的load/store等方法,而CMP EntityBean,使用CMP Peristence Engine來做這個(gè)工作)。這樣,就隱式的持久化數(shù)據(jù)了。不需要,你像Hibernate那樣調(diào)用session.update這樣的語句。EntityBean這種同步方式是對(duì)它性能差的重要原因之一。值得注意的是,EJB Implements對(duì)于EntityBean同步并不完全是我上面描述的那樣,同步的頻率和事務(wù)、特定的implements是緊密相關(guān)的。
|
總的來說,CMP EntityBean O/R Mapping Engine是為靜態(tài)的、功能固定的EntityBean的O/R Mapping提供支持而開發(fā)的。而Hibernate擔(dān)任的是一個(gè)Layer的作用。
四、 Spring不是神話
Rd Johnson聰明在哪里?聰明在,他堅(jiān)持了自己的實(shí)踐,而不是隨大流。Rd Johnson認(rèn)識(shí)到90%的應(yīng)用不需要分布式、不需要J2EE中那些重量級(jí)的技術(shù),譬如JNDI,他就動(dòng)手為EJB脫去Remote這層皮、將大多數(shù)應(yīng)用中不必要的技術(shù)隔離、改造。從適用范圍上來說,Spring對(duì)EJB做了90%的補(bǔ)充。
個(gè)人看法:Spring的哲學(xué)在于,framework針對(duì)最常見、最簡單的應(yīng)用場景而設(shè)計(jì),等到需要特殊技術(shù)的時(shí)候,再想辦法解決問題。這樣,在絕大多數(shù)沒有特殊要求的應(yīng)用中,Spring就顯示出優(yōu)勢來了。下面,我們會(huì)做詳細(xì)的講解。
4.1 Spring“無侵入性“是謊言,但是有資格笑”百步之外的EJB”
“無侵入性”是Spring標(biāo)榜的特性。但是,我想說,Spring的“無侵入”是謊言,隨著應(yīng)用的深入,“無侵入”對(duì)什么framework來說,都是個(gè)神化。
什么就叫“無侵入性”?部署到Spring中的Object不需要強(qiáng)制任何實(shí)現(xiàn)接口就可以說Spring是“無侵入性”的?我覺的,這是大錯(cuò)特錯(cuò)。如果你非要說,Spring的確不需要像EJB那樣強(qiáng)制實(shí)現(xiàn)一些接口,那么我只能告訴你:
(1)Spring設(shè)想的Object的應(yīng)用場景是從最簡單的出發(fā)。所以,它沒有,為了一些預(yù)料中要使用的特性而強(qiáng)制Object實(shí)現(xiàn)一些特定的接口。但是,事實(shí)上,在Spring中,如果你的應(yīng)用場景稍微深入一點(diǎn),那么你就和和Spring綁定了。
(2)Spring管理的Object,從某種意義上說是沒有狀態(tài)的。
針對(duì)第一點(diǎn),我舉兩個(gè)個(gè)例子。(1)EJB內(nèi)部方法的調(diào)用,會(huì)導(dǎo)致基礎(chǔ)設(shè)施不會(huì)起作用。但是Bean接口(SessionBean、EntityBean、MessageDrivenBean)中都有可以使Bean獲得自己Context的支持,譬如:SessionBean的setSessionContext(SessionContext ctx) 等等,容器部署B(yǎng)ean的時(shí)候會(huì)通過它給每個(gè)Bean設(shè)置一個(gè)上下文。而EJBContext中,有EJBObject getEJBObject這樣的函數(shù),可以使得Bean獲得自身的EJBObject,這樣通過EJBObject來調(diào)用Bean自己的函數(shù),基礎(chǔ)設(shè)施就會(huì)起作用了。而Spring中,如果,一個(gè)Object的函數(shù)需要調(diào)用自己的其它函數(shù),而又希望譬如安全檢查、事務(wù)等等Aspect起作用?那么Spring,怎么做?你需要設(shè)置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.
|
所以,當(dāng)你需要上面說的內(nèi)部調(diào)用需要基礎(chǔ)設(shè)施起作用的特性,不管在EJB還是Spring肯定需要和特定框架綁定的。為什么說,Spring五十步笑百步?因?yàn)椋疑厦嫣岬剑?/span>Spring在Object很簡單的情況下,是可以任意部署的、復(fù)用的。而EJB卻不管你需不需要,開始就設(shè)想你需要的。同樣,Spring中的BeanFactoryAware、BeanNameAware等等接口也都說明了一點(diǎn):Spring將特性從Object剝離,從而,盡量降低它的依賴性。只有當(dāng)你的Object復(fù)雜的時(shí)候,framework才會(huì)侵入你的Object。
針對(duì),第二點(diǎn),我想著重談一下。為什么說,從某種意義上說Spring中部署的對(duì)象是沒有狀態(tài)的?我們知道,Spring支持兩種Object:Singleton和Prototype。Spring Spec中,認(rèn)為,Singleton可以稱為stateless的,Prototype可以稱為是statefule的。而在EJB的世界中,StatefuleSessionBean和EntityBean也稱作是stateful的。那么,它們的stateful分別意味著什么?它們?yōu)槭裁丛谝蕾囆苑矫嬗心敲创蟮膮^(qū)別?為什么Spring中的Object不需要實(shí)現(xiàn)特定接口,而EJB需要?先來,看看EJB的SessionBean接口:
|
|
|
|
|
|
|
|
|
|
|
|
其中的setSessionContext我上面說過。看ejbActivate()、ejbPassive(),為什么會(huì)有這兩個(gè)函數(shù)?而Spring不需要實(shí)現(xiàn)有同樣函數(shù)的接口?這是EJB和Spring的對(duì)象管理機(jī)制的不同造成。EJB implements一般來說,為了復(fù)用Bean,會(huì)采用一級(jí)Cache加上一級(jí)InstancePool(StatelessSessionBean是不需要Cache的),從而支持將StatefulSessionBean持久化到磁盤,支持EntityBean的Bean Instance(注意這個(gè)Bean Instance和client得到的EntityBean是不同的,它沒有和任何的DB Record關(guān)聯(lián))的復(fù)用,這就導(dǎo)致了ejbAcrivate、ejbPassivate等的引入。但是,Spring沒有采用這樣管理機(jī)制,它只有Singleton/Prototype。而Prototype雖然也可以說成是Statefule的,但是它不會(huì)在不同的client中復(fù)用Object Instance,而是每一個(gè)client一個(gè)對(duì)象,哪怕一萬個(gè)client,那么就產(chǎn)生一萬個(gè)Instance,而在EJB中,可能使用100 Instance來服務(wù),將not active的Bean持久化到磁盤,復(fù)用Bean Instance。還請注意,這里我不是說EJB中的StatefuleSessionBean好,事實(shí)上我發(fā)現(xiàn),一般來說,當(dāng)并發(fā)量很大時(shí),采用節(jié)約內(nèi)存而持久化Bean到磁盤這種策略,I/O瓶頸引起的問題更為嚴(yán)重。
再看,ejbRemove,這個(gè)沒什么多說的,Spring中你可以選擇實(shí)現(xiàn)InitializingBean、DisposableBean接口,但是Spring推薦不要這樣做,可以寫普通的init成員函數(shù),然后在配置文件中指明init-method、destroy-method屬性,這樣避免和Spring框架的綁定。
總的來說,Spring從對(duì)象最基本的引用場景出發(fā),當(dāng)需要復(fù)雜特性的時(shí)候,才會(huì)采用特殊機(jī)制來解決問題,也就是在這時(shí),才會(huì)使應(yīng)用綁定到Spring中。所以,它的侵入性比較低,但是不是“無侵入性”,不是你想的那么美好,當(dāng)然,也沒有“絕對(duì)無侵入“的framework。
4.2 我覺的Spring IOC的設(shè)計(jì)思路不夠完美
Spring的IOC被一些人當(dāng)作多么神奇的東西。
EJB具有Spring中所說的那種IOC的能力嗎?答案是肯定的。EJB中的EJB引用、資源引用、環(huán)境屬性都可以說是IOC,不是嗎?然而,Spring和EJB的IOC不同在哪里?
Spring注入的特色:主要考慮Local Object的查找,這個(gè)時(shí)候不需要任何的協(xié)議(譬如JNDI),當(dāng)你需要注入Remote Object的時(shí)候,采用RMI協(xié)議或者使用第三方Tool(譬如Hessian)。
EJB的特色:無論你的Bean-Bean是否部署在同一臺(tái)機(jī)器上、Client->Bean是否在同一臺(tái)機(jī)器上,肯定需要通過JNDI來查詢Bean,只是,如果是它們在同一臺(tái)機(jī)器上的時(shí)候,你使用Local接口,這樣使得調(diào)用變?yōu)?/span>Local調(diào)用,從而提升性能。EJB它從出生時(shí)起,就定位為分布式組件架構(gòu),一頭栽進(jìn)“distributed”不容易出來了。這個(gè)可能就叫“尾大不掉”吧。
這一切的不同,只能說,它們的定位不同。一個(gè)更關(guān)注Local、一個(gè)更關(guān)注Remote。Spring仍然堅(jiān)持它的哲學(xué),從最基本的、大多數(shù)的場景考慮起,到特殊需要的時(shí)候,再想辦法來解決問題。它試圖找到J2EE開發(fā)和系統(tǒng)能力的均衡點(diǎn)。
可以說,Spring的做法,更加合情合理。但是,我也相信,Spring在”只是為Remote注入提供簡單的支持“這一點(diǎn)上有點(diǎn)矯枉過正。我覺的,它可以做的更好,譬如通過作為J2EE標(biāo)準(zhǔn)的JNDI來封裝Local、Remote查找。
目前,Spring不怎么關(guān)心Remote Object注入,對(duì)于需要Remote注入的情況,只提供簡單的支持,而且還需要針對(duì)expert單獨(dú)寫配置信息。在這里,EJB3.0的做法,我覺的,是目前,最方便、最理智、也是最有前途的。EJB3.0通過@remote、@local就可以讓EJB Server做不同的部署。
Spring導(dǎo)出遠(yuǎn)程對(duì)象。
<bean class="org.springframework.remoting.rmi.RmiServiceExporter">
<!-- does not necessarily have to be the same name as the bean to be exported -->
<property name="serviceName"><value>AccountService</value></property>
<property name="service"><ref bean="accountService"/></property>
<property name="serviceInterface"><value>example.AccountService</value></property>
<!-- defaults to 1099 -->
<property name="registryPort"><value>1199</value></property>
</bean>
|
Spring中注入Remote是怎樣做的?
<bean class="example.SimpleObject">
<property name="accountService"><ref bean="accountService"/></bean>
</bean>
<bean id="accountService" class="org.springframework.remoting.rmi.RmiProxyFactoryBean">
<property name="serviceUrl"><value>rmi://HOST:1199/AccountService</value></property>
<property name="serviceInterface"><value>example.AccountService</value></property>
</bean>
看了,這段代碼,你就知道了。
這種方法非常的輕量級(jí),從本質(zhì)上來說,這種方法和JNDI沒有任何的不同,這種方法,也需要一個(gè)NamingService,還記得RMI編程中,運(yùn)行服務(wù)端的時(shí)候,首先運(yùn)行rmiregistry,這個(gè)實(shí)際上就是非常簡單的NamingService??磥?,Rd Johnson對(duì)JNDI真是深惡痛絕啊。怎么也不愿意用JNDI。Spring這種方法,也許沒有JNDI那樣重量級(jí),但是很顯然它不能支持工業(yè)級(jí)分布系統(tǒng),J2EE發(fā)展到今天,JNDI已經(jīng)成為最核心的技術(shù),它不是簡單的Object Naming Service,它提供標(biāo)準(zhǔn)接口來定位用戶、微機(jī)、網(wǎng)絡(luò)、對(duì)象、服務(wù)器等等。它已經(jīng)廣泛而深入的進(jìn)入J2EE技術(shù)的各個(gè)領(lǐng)域、成為J2EE系統(tǒng)的紐帶。
舉個(gè)很簡單的例子:我需要在Spring應(yīng)用中動(dòng)態(tài)獲取Remote Object,我該怎么做?我需要無縫使用LDAP,我該怎么做?答案是,Spring不能幫到你什么。
那么我就想,Spring為什么不使用JNDI來封裝Local、Remote查找兩種協(xié)議?從而,使用J2EE標(biāo)準(zhǔn)來實(shí)現(xiàn)無縫“注入”。這樣帶來的優(yōu)點(diǎn)就是:(1)適應(yīng)JNDI已經(jīng)廣泛而深入滲透的領(lǐng)域(2)JNDI是J2EE標(biāo)準(zhǔn)(3)支持動(dòng)態(tài)Remote Service獲取(4)支持工業(yè)級(jí)分布系統(tǒng)。
Properties props = new Properties();
pros.put(“searchServiceFactory”,”org.net.spring.bean.BeanFactory”);
Context ctx = new Context(env);
ctx.lookup(“servicename”);
Properties props = new Properties();
pros.put(“searchServiceFactory”,”com.sun.j2ee.jndi”);
Context ctx = new Context(env);
ctx.lookup(“servicename”); |
|
從下面,你可以看出,我個(gè)人認(rèn)為Spring如果仍能OS,free,也許還會(huì)有很多人選擇它,但是如果,它試圖商業(yè)化,那么可以肯定它必須向EJB3.0靠攏。向標(biāo)準(zhǔn)靠攏。
|
4.3 獨(dú)立的、完整的、面向Programmers的AOP框架才是Spring真正的亮點(diǎn)
EJB具有Spring中所宣揚(yáng)的AOP能力嗎?答案是肯定的。EJB的基礎(chǔ)設(shè)施就是使用AOP技術(shù)實(shí)現(xiàn)的。然而,我要說,EJB的AOP并沒有面向Programmers。為什么這么說?EJB Implements為你提供一組基礎(chǔ)設(shè)施(例如,JBOSS中那些可配置的interceptors)。你可以根據(jù)系統(tǒng)需要配置。但是,你不可以編寫自己的interceptor,然后配置到系統(tǒng)中。因?yàn)?/span>EJB的interceptors往往和EJB Implements內(nèi)部愈合很緊,你想編寫自己的interceptor,意味著你必須閱讀EJB Implements的source,了解它的實(shí)現(xiàn)。換句話說,EJB Implements中的AOP技術(shù)是為了EJB Server能夠提供基礎(chǔ)設(shè)施而使用的,它沒有想到為programmer提供更多的AOP能力。而Spring的AOP開始就是作為一個(gè)框架來發(fā)展的,是獨(dú)立的、完整的。造成這種情況,是歷史的原因。EJB Implements作者也不是神人,他們不可能,N年前,就想到將AOP框架設(shè)計(jì)的足夠獨(dú)立,從而面向programmes。
|
個(gè)人觀點(diǎn):EJB3.0在基礎(chǔ)設(shè)施方面的說明,基本沿襲EJB2.X的。只是,可以提到EJB3.0支持通過annotations來使用基礎(chǔ)設(shè)施,沒有說,EJB3.0需要完善的AOP框架,但是,我想,EJB3.0 Implments應(yīng)該都會(huì)提供一個(gè)獨(dú)立的、完整的、面向programmer的AOP框架。事實(shí)上,JBOSS不早就有了J
|
當(dāng)然,在Spring中使用AOP也不是那么的輕松,譬如,讓你自己寫TransactionProxy,你還是需要了解Spring AOP內(nèi)部運(yùn)作機(jī)制的。
4.4 Spring對(duì)其它框架的集成
這個(gè)問題,就不談了。
五、EJB將走向何方
5.1 EJB-3.0
我們沒必要說EJB2.X本身有多少的缺陷,畢竟,它是前一個(gè)J2EE時(shí)代的產(chǎn)物,只能說EJB2.X已經(jīng)不能反映大多數(shù)J2EE應(yīng)用的實(shí)際需要。過時(shí)了。那么EJB3.0打算帶我們走向何方?
EJB3.0 Spec除了針對(duì)簡化開發(fā)、方便測試、方便部署等目標(biāo)做了不少的修改,更重要的是EJB3.0對(duì)SessionBean,特別是EntityBean模型做了一個(gè)全面的整容手術(shù)。這種修改是革命性的。
在我的《如果我來改進(jìn)EJB2.X模型》中,我談到,如果,讓我對(duì)EJB2.X的EntityBean模型做修改,那么首先需要為新的模型定好位。就拿EntityBean來說好了。
第一條路:繼續(xù)EntityBean設(shè)計(jì)的初試?yán)砟睿?/span>Remote Domain Model(包括BMP EntityBean代表的Domain Model和CMP EntityBean代表的AnaemicDomainObject),并且保留Local接口,力圖改經(jīng)持久模型的設(shè)計(jì),提高性能(即使CMP EntityBean的性能也是難以令人接受的,這種情況,我個(gè)人認(rèn)為,主要是因?yàn)?/span>EntityBean模型設(shè)計(jì)的不好,在我的另一篇《如果我來改進(jìn)EJB2.X模型》中有深入的分析)、增強(qiáng)功能(EJBQL實(shí)在太弱),讓那些連SessionBean、EntityBean都需要部署在不同Server上的應(yīng)用來為EJB2.X的EntityBean留口氣。
但是,顯然,EJB Server提供商是不可能甘心這一點(diǎn)羹的,因?yàn)槟菢拥膽?yīng)用實(shí)在太少了。事實(shí)已經(jīng)證明,如果EntityBean的Remote不是必須的,那么RemoteEntityBean性能上是不可行的,它只能工作在SessionBean后端,然而,即使EntityBean工作在SessionBean后端,但是EntityBean本身的局限性也太多,粒度要么太粗要么太細(xì),性能、功能太弱,等等,開發(fā)數(shù)據(jù)應(yīng)用非常地蹩腳,那么如果,在Remote EntityBean不是必須的情況下,我為什么不完全放棄EntityBean,在SessionBean后端使用其它的O/R Mapping Tool來開發(fā)數(shù)據(jù)應(yīng)用,譬如Hibernate。這就是,EntityBean可以走第二條路。當(dāng)然,從某種意義上來說,也是它必須走的路。
第二條路:完全拋棄EntityBean,采用Hibernate這樣的O/R Mapping Engine作為Session Bean、Message-Driven Bean的后端數(shù)據(jù)持久化工具。而從EJB3.0可以看出,EJB3.0的確完全拋棄了傳統(tǒng)的EntityBean模型。個(gè)人意見:可以這樣說吧,EntityBean已經(jīng)不復(fù)存在,Expert Group在SessionBean下給你換上了一個(gè)非常sharp的Persistence engine,你拿著engine,想干什么就干什么好了(上面講過,EntityBean中,PersitenceEngine對(duì)client是通明的,這是由這兩種引擎的本質(zhì)作用決定的。有人說,EntityBean Application中不可以使用Dynamic Query,只能在配置文件中申明EJBQL,這些都是兩種Persistence Engine的本質(zhì)所決定的)。蹩腳的、強(qiáng)制模型的EntityBean不復(fù)存在!另外,EntityBean Remote特性在EJB3.0中根本沒有提到,或許只是作為一個(gè)可選特性了吧(我還沒有想到,EJB3.0中,如何來支持Remote PO,這個(gè)問題很詭異)??磥恚?/span>Expert Group已經(jīng)徹底否定了EntityBean的設(shè)計(jì),或者說EntityBean的確是不符合實(shí)際需求的,Remote EntityBean、Remote Domain Object在絕大多數(shù)情況下是不切實(shí)際的。
|
話外題:Hibernate和JDO的關(guān)系,很微妙。EJB3.0和JDO的合并、Gavin進(jìn)入EJB3.0 ExpertGroup令人很迷惑。EJB3.0的持久化模型采用JDO,應(yīng)該是理所當(dāng)然的。但是,目前,EJB3.0的Persitence Engine部分似乎被Hibernate左右,那么JDO的位置應(yīng)該在哪里?
|
六、Spring將走向何方
無疑,“聽起來很美妙的”IOC、實(shí)力、實(shí)用派Spring AOP、集成大量framework的Spring是目前、對(duì)分布式、高級(jí)J2EE特性要求不強(qiáng)的系統(tǒng)的最合理選擇。但是,你可以看到,Spring能做到的,除了集成大量framework這個(gè)特性外(當(dāng)然這個(gè)永遠(yuǎn)不會(huì)被寫進(jìn)EJB Spec,但是如果EJB Server供應(yīng)商想這樣做,也是非常簡單的事),EJB3.0也能做到,而且很多地方做的比Spring好很多,最重要的,EJB是標(biāo)準(zhǔn),所以,很肯定的說,如果Spring OS、free,保持目前的姿態(tài)發(fā)展,仍然會(huì)成為開發(fā)人員不錯(cuò)的選擇,然而,如果Spring試圖商業(yè)化,我是Rd Johnson的話,我會(huì)向EJB3.0靠攏,搖身成為EJB3.0 Server提供商。
七、EJB3.0是J2EE商用framework的未來
大肆革新過的EJB3.0,是J2EE商用framework的將來。
|
|