轉貼:Spring vs. EJB

zjsun發表於2005-02-03

引自:http://www.cnblogs.com/raimundo/archive/2004/09/20/44697.html

我知道我要挨扳磚,沒事,來吧:)

赫赫,我來說一下spring vs EJB,首先強調,我不是ejb的擁護者,但我欣賞他的完整、他的學院氣,同時也深感他的硬傷,我不是spring的擁護者,雖然去年3、4月間看

到spring的時候曾經讓我眼前一亮。對ejb有太多的誤解,對spring有太多的吹捧,我希望這是一個相對公平的比較.

我認為spring和ejb的差異在這樣三個方面,一個是受眾也就是這兩個叫framework也好叫platform也好的東西的scope;另一個是component architecture,最後一個是語義

1.Scope比較

先說scope,ejb的scope是什麼?ejb針對什麼系統來設計的?這個我想一個人一個答案,我說了不算,同樣大家說了也不算,我們來看規範(題外說一句,我想本來我沒啥

資格在這裡談論ejb,我應用ejb的專案不多,但是我有個習慣,就是讀規範學技術,不管別人怎麼說先看這個東西是怎麼來的,我想這一點還使我有些開口的自信,不至於太

貽笑大方),ejb規範的頭幾句:

Enterprise JavaBeans is an architecture for component-based computing.Enterprise beans are components of transaction-oriented enterprise

applications.

好了,很明確,ejb是針對transaction-oriented enterprise application的元件,那麼也就使說ejb是面向以事務為中心的企業軟體,而不是別的。ejb的核心是

transaction,不是domain model或別的。

why transaction?我在電力行業做過一陣資訊化軟體架構師,在電力這樣一個需要處理大量資料的領域裡,很少有oo model,而是做完entity分析,交給dba去優化,以資料

效能為主,這樣的系統裡,資料操作的粒度就是transaction,而不是object或是別的。我想這該算是一個大型企業級系統,我看到的是transaction,因此ejb這個把scope定

在enterprise級的東西而言,這樣的設計還使合理。而且ejb對transaction這部分的處理確實比較完整,cmt,bmt,不同的transaction scope控制的都很好。基於這種認識,

我認識transaction script是ejb的標準應用模式,而不是domain model或是別的。

這是對ejb最大的誤解的來源,我看過的所有ejb書裡,只有o'reilly的一本隱約提到transaction是ejb的中心。其他一律不提,瘋狂的鼓吹ejb多好多好ejb多麼萬能,我想

,如果不知道ejb是transaction-oriented的,那麼ejb奇怪的物件模型的確不可接受。

再說spring,spring是什麼呢?我沒有看到特別明確的定義,不過我想仿照ejb,定義spring為:

Spring is a Javabean-based framework that supporting component architecture development.Spring provides lighter context for heterogeneous entrprise

application.

我e文很差,cet-6 6次都沒過,我想說明的是,spring是一個輕量化的元件架構,可以支援多種企業應用程式模式.看到這裡有人又該說了,no,no還有ioc,還有aop,沒錯這

些很cool的特性我沒說,但是包含了,component architecture意味著兩個方面,component working(編寫元件)和container working(編寫容器環境),spring的ioc和aop是

用在container working裡的.當然肯定還有其他的一些沒有概括,但是我想主體我還是說到了的.這樣scope就很明確了,spring的基礎是javaBean,javaBean支援完整的oo建

模,因此spring可以適用更多的結構,domain model和別的一些。

那麼開始比較,spring有一個理論上普適的元件模型,但是鑑於大型應用多為transaction-oriented,那麼用spring的理由就是domain model,ejb不能提供完整的oo模型而

spring可以。

結論:由於scope不同,其實比較spring和ejb那個更適合企業開發沒什麼意義,因為這裡面根本就是兩個不同的範疇,在scope上指責ejb不如spring,就好像說raimundox,你

就不能替老婆把孩子生了,還讓她那麼痛苦的懷胎十月。其實我也不想,我也想替,可惜我們這功能.....扯遠了,ejb也是,沒這功能你怎麼強求他呢?你要說ejb設計的不好

,也不對,人家有專門的領域。因此我說,在scope上比較spring和ejb沒意義,根本不是一個級別的。

2.component architecture

Component architecture有一個基本觀點,就是component和context的分離,理想情況下,component只負責業務的實現,而container提供context,這個context只技術

context,比如事務比如安全的支援。於是,component architecture的基本觀點就是business關注點和technique關注點分離,business由component負責,technique由

context或者叫container實現。那麼很明確了,component architecture裡有兩種程式設計,針對component的和針對container的。

好,有了這個理解,我們可以繼續了,如果有人有疑意,那麼抱歉,這片文章並不適合您,後面全部的論點都是基於這個觀點的,如果不認可這個,下面的也不會認可,您

也不用浪費時間了。

首先看ejb的component方面,ejb在component architecute做得非常的好,ejb就是一個業務元件,在container-managed的情況下,元件通過宣告可以應用容器提供的技術

context,當container-managed不滿需要的情況下,可以bean-managed,只要保持對外的事務語義就可以了(記得嗎?ejb是transaction-oriented,事務最重要)。在ejb裡

,元件和容器的約定非常明確,哪些需要元件寫,哪些是容器提供的非常明確,這是component architecture裡很好的習慣,明確元件和容器的界限(ejb的一個缺點,矯枉過

正,有一些操作也被禁止)。編寫程式碼非常容易,業務,only業務。其實ejb的規範裡,ejb的coder其實最好是domain expert,實現業務邏輯就好了。

現在來看spring的component方面,spring以javaBean為基礎,貧容器,也就是對容器沒要求,於是,spring第一個缺點,contianer和component的約定不清晰(寫到這裡我

已經聽到一些人在叫了,這是spring的優點,自由,別急,後面我會證明這是spring的軟肋),但是spring用了一種比較聰明的辦法,那就是加強container working.

看一下spring的container working,通過spring的aop api,我們可以很容易的為特定元件定製容器環境,把一個元件需要的容器技術環境以aspect的形式weave到component

裡,非常的靈活,也非常的強大,spring通過這種形式來彌補元件/容器約定不足的情況,一切由component選擇,容器除了裝配(ioc/dip)不提供任何技術context,想要什

麼自己來,這個給了component實現者自己選擇的權利,很好(但也隱含了spring的最大的不足,別急我後面會說)。

再來看ejb,非常遺憾,ejb container working的能力幾乎為0,當然算上jca的話還不算太差,但是那只是資源,而不是技術context。why?因為ejb認為他已經提供了所有

企業級開發所必需的技術context了,事務(ejb裡我總把他放在第一位)、分佈、併發、安全等等。在ejb看來container working的能力幾乎無用,而且不安全,除了jboss開放

了比較多的container working介面其他的ejb container提供這方面的支援很少很少.當然提供很多技術context並不是壞事,要命的是不能配置,要麼全用要麼不用(倒是很

原子),這是ejb最大的不足,容器環境不可配,也是spring強於ejb的地方。

上面我們已經看到了spring和ejb都是component architecture,那麼component能想到的最直接的用處就是複用。那麼比較這一點就是比較ejb和spring component

architecture的關鍵。看到這裡spring的支持者們該常出一口氣了,spring複用一定強於ejb複用,赫赫,但我的結論正好相反,ejb複用優於spring複用!!收起你們的憤怒

,收起你們不屑,聽我把話說完。

在component architecture裡,component是業務實現,而不該有技術程式碼,就算用也要通過容器環境去和容器互動來完成操作,比如ServletContext等東西。那麼其實

組建結構下複用的關鍵不是組建而是容器!!

以前有一個頗有名氣的dx(gigix別看了,說你呢),說"COM和EJB都鼓吹模組化和複用,模組化是真的,複用是騙人的",com我不是很熟,不好下結論,ejb呢?ejb不易複用我

承認,但是騙人嗎?不騙,後面我給出一種ejb複用的思路大家參考。反正元件一點技術都不作,只有業務邏輯想用就要有相應的容器環境,那麼容器環境的複用性才是元件復

用的關鍵。ejb不易複用是因為如果脫離容器,我們就必須給它提供相應的技術context,事務、分佈、併發等等一個也不能少,因此容器外複用ejb效率很低。注意,

是容器外,元件本來就是跑在容器裡的,誰讓你非要拿出去用),而容器內呢?因為ejb規範規定ejb容器應該相容,別說webSphere到bea的移植有多難,其實不難,或

者說難度比把spring元件移植到pico複雜一點,當然你用vendor-specified的特性就沒辦法了,這不再規範內,你違規就別怨人家。因此,ejb的複用是可以的,而且是規範保

證的,容器外也有辦法,也不是很難,我後面說。

再看spring,的確他很靈活,但這正是致命傷,component完全是業務實現,但是容器呢?spring怎麼保證容器的環境?沒有,只能你自己保證,當你沾沾自喜的說,spring

裡的component都是pojo,可以很好複用的時候,可曾想到,這複用的代價是要複用容器。比如有個componentA,在SystemA裡需要事務模型A和安全模型A,在SystemB裡需要事

務模型B和安全模型B,當你從SystemA裡複用componentA的時候,你要怎樣?重寫事務模型B和安全模型B,然後你可以堂而皇之的說,你複用了元件。的確,你複用了元件,但

是你重寫了容器,值嗎?更可怕的是,spring容器和元件沒有約定,那麼怎麼保證你的組建不寫技術程式碼?ejb只要Bean-Managed並提供統一的事務模型就好了,spring呢?你

靠什麼保證?你自己?這是spring一大硬傷,完全container-managed下缺少特定的component邊界控制.你可以說,特殊要求的事務模型ejb還實現不了呢,的確,這是有可能

,但是ejb transaction model不能適用的情況有多少?如果真的不行,只能說ejb的簡單複用在這裡失效。

對於元件還有一個問題就是部署,這也是ejb為人詬病的地方.的確,ejb的部署夠複雜,但在ejb規範裡有一個專門的角色來負責部署的,ejb是component architecture,那

麼比如有一個人來粘合技術和業務,這個人不該是programmer(我剛才說了,ejb的實現者最好是業務專家,實現業務邏輯),ejb的部署才是很厲害的人,他需要知道什麼業務

需要什麼樣的技術支援,該怎樣得到效能,因此deployer才是ejb architecture裡最牛的,我重來不以為寫ejb的是高手,但是一直都敬仰ejb的deployer.當然這裡有一個除錯

困難的問題,這是ejb的硬傷,沒辦法,這甚至是元件開發的硬傷.

再來看spring,spring宣稱他部署簡單,我覺得rod johnson在轉移視線,想想看,打成一個war和打成一個ear有多大的區別?那麼部署的差異在哪?差異在ejb的deploy

description和spring的context.xml的編寫上!在用spring開發中要有一個人來寫context.xml這個人往往比較瞭解系統,知道什麼元件用什麼攔截,那個元件依賴那個,甚至

會是架構師在作這件事情,那麼和ejb裡對系統有大局觀的人來做deploy有多大區別?可能就是Xml的編寫吧,我想在工具的支援下就是熟練度的問題,因此我覺得部署上

spring和ejb差不多,spring不用啟server,除錯放便些。

結論,在component architecture上,spring靈活,ejb統一完整,各勝擅長,spring的靈活以降低複用為代價,但是如果有common的技術實現,的確很好複用,但是

spring+一套common的技術實現也就約等於ejb了吧?

3.語義

那麼spring複用的問題表明了什麼呢?其實是缺乏語義的支援,ejb開發可以看作在一個統一的語義環境下來作的,這個語義由ejb規範規定,因此ejb的複用有語義保證,而

spring呢?貧語義,一切都要開發者自己來實現。因此,如果ejb的環境語義可擴充套件並且可配置(比如去掉分佈),那麼spring毫無優勢,標準的一致的完整的元件架構使ejb

會大有作為,但是現在並沒有,才有了spring的火爆.這是一種畸形的勝利,完備語義的輸給了貧語義的,問題是什麼,強迫消費...誰讓ejb非得強迫客戶去買用不到的分散式

環境的單?但是統一語義的威力不會因此掩滅,現在有兩條路,spring聯合os社群,制定lightweight j2ee語義集合,爭取成為標準。第二,ejb實現技術語義可配置可擴充套件。

誰會勝利?不好說,但是似乎ejb的腳步快一些!

附:容器外複用ejb

其實ejb在容器外完全是可以用的,但是為了最大限度保證能用,bean-managed是推薦(不是cmp,bmp而是cmt,bmt),那麼怎麼傳送一個transaction進去?SessionContext(

好像是這名記不清了,都快2:00了,困呀...就是ejb那個context介面),一個介面嘛,自己mock一下,給一個transaction進去就好了。怎麼裝配?spring的setter

injection。如果用spring,那麼cmt也可以實現,攔截啦,不過就看能不能實現ejb transaction model了。entity bean,如果是bmp,就用它好了,cmp,繼承一個上

hibernate。這些都模擬好了,找一個in memory的jndi,把spring context封進去,這樣相當於我們用spring實現了一個lightweight ejb container(其實就是給spring一個

ejb api的皮),輕到什麼程度?除了注射什麼都沒有。

然後client就可以構造jndi,然後lookup了

看到這裡一定有人說,你吃飽了撐的,這麼費勁容器外複用ejb,為什麼不直接用spring,這樣也不夠pojo,每個元件都有ejb的類的繼承,好,我告訴你這麼做的好處,首先

,雖然不夠pojo,但是足夠bean,因此spring來管理ejb是可以的,證明我的觀點容器外使用ejb可以(赫赫,不要說偶rpwt...).其次的,當業務發展了,你的系統需要分佈了

,把spring去掉,拿出ejb,redeploy,ok了,延展,穩定,分佈都有了,這才是複用該有的境界,改一個部署整個環境換掉,去掉lightweight的ejb container,換乘

heavyweight的就是重量級。

當然這麼實現很難,在ejb3裡會容易些,我敢打賭,spring以後一定是lightweight ejb container的供應商,免不免費,os不os要看rod johnson了,不過我覺得希望不大。

致謝:

首先感謝dlee,在和他的討論中形成了這篇文章的主題,然後是冰雲,他幫我審稿直到2:04,udoo,perhaps都提出了中肯的意見,謝謝他們.

當然也歡迎大家訪問我的blog:www.cnblogs.com/raimundo

相關文章