天天看點

POJO與Spring和EJB 3.0的對比

簡化企業級軟體開發的關鍵是提供一個隐藏了複雜性(例如事務、安全性和永續性)的應用架構。良好設計的架構元件可以提升代碼的重複使用(reuse)能力,提高開發效率,進而得到更好的軟體品質。但是,目前J2EE 1.4中的EJB 2.1架構元件被人們普遍認為是設計較差的和過于複雜的。Java開發者對EJB 2.1很不滿,他們已經試驗了多種其它的用于中間件服務傳送的方法。最引人注目的,下面兩個架構元件已經引起開發者的巨大興趣和積極的反映。它們很可能成為未來企業級Java應用程式可供選擇的架構元件。

◆Spring架構元件是一個流行的,但是非标準的開放源代碼架構元件。它主要是由Interface21 Inc.公司開發和控制的。Spring架構元件的架構是基于依賴注入(DI)設計模式的。Spring可以單獨地或者與現有的應用程式伺服器一起工作,它大量地使用XML配置檔案。

◆EJB 3.0架構元件是一個标準的架構元件,由Java社群組織(JCP)定義,并受到所有主流的J2EE廠商支援。預釋出的EJB 3.0規範的開放源代碼和商業實作都可以在JBoss和Oracle上看到了。EJB 3.0大量使用Java注釋(annotation)。

這兩個架構元件的核心設計理念是相同的:兩者的目标都是把中間件服務傳遞給松散耦合的簡單舊式Java對象(POJO)。這些架構元件通過在運作時截取執行内容或向POJO注入服務對象,把應用程式服務與POJO捆綁在一起。POJO本身不關心捆綁的過程,并且對架構元件幾乎沒有依賴。其結果是,開發者可以聚焦于業務邏輯,個人可以在沒有架構元件的情況下測試他們的POJO。此外,由于POJO不需要從架構元件中繼承或實作架構元件接口,開發者建立繼承結構和建構應用程式的時候都有高度的靈活性。

但是,盡管兩者的設計理念是相同的,它們傳遞POJO服務時卻采用了完全不同的方法。盡管目前已經出版了大量的圖書和文章來把Spring或EJB 3.0與EJB 2.1進行對比,但是它們都沒有對Spring與EJB 3.0之間的差異進行認真的研究。在本文中,我将研究Spring和EJB 3.0架構元件之間的關鍵差異,并讨論它們的優缺點。本文的主題也可以應用在其它一些名氣稍小的企業級中間件架構元件上,因為它們都聚焦于"松散耦合的POJO"設計。我希望本文能夠幫助你選擇符合需求的最佳的架構元件。

廠商無關性(Independence)

開發者選擇某種Java平台的一個最重要的理由就是該平台的廠商無關性。EJB 3.0是一個開放的、标準的、具有廠商無關性的平台。EJB 3.0規範是由企業級Java團體中所有主流開放源代碼和商業廠商開發和支援的。EJB 3.0架構元件把開發人員與應用程式伺服器實作(implementation)隔離開來了。例如,盡管JBoss的EJB 3.0實作是基于Hibernate的,而Oracle的EJB 3.0實作是基于TopLink的,但是開發人員并不需要學習Hibernate或TopLink的特殊API,就可以讓他們的應用程式在JBoss和Oracle上運作。廠商無關性把EJB 3.0架構元件與其它的POJO中間件架構元件區分開來了。

但是,很多EJB 3.0的批評家迅速指出,在寫這篇文章的時候,EJB 3.0規範還沒有達到最終發表的版本。在EJB 3.0被所有主流的J2EE廠商采用之前可能還需要一到兩年時間。但是,即使你的應用程式伺服器還沒有自然地(natively)支援EJB 3.0,你還是可以通過下載下傳和安裝一個"嵌入式的" EJB 3.0産品,在伺服器上運作EJB 3.0應用程式。例如,JBoss嵌入式EJB 3.0産品是開放源代碼的,可以在任何與J2SE-5.0相容的環境中(例如,在Java應用程式伺服器中)運作。它現在正在進行beta測試。其它的廠商也可能很快釋出他們的嵌入式EJB 3.0産品,特别是用于規範的"資料永續性"部分的産品。

另一方面,Spring一直是非标準的技術,而且在可以預見的未來它仍然是這樣的。盡管你可以把Spring架構元件與任何應用程式伺服器一起使用,但是Spring應用程式都被"鎖定"在Spring自身和你所選擇的內建到Spring中的特定服務中了。

◆盡管Spring架構元件是一個開放源代碼項目,但是它仍然擁有配置檔案的專利XML格式和專利程式設計接口。當然,這類"鎖定"發生在任何非标準的産品上,Spring也不例外。但是它卻造成了:你的Spring應用程式的長期生存能力依賴于Spring項目本身(或Interface21 Inc公司,它雇傭了大多數Spring核心開放人員)。此外,如果你使用任何Spring特定的服務,例如Spring事務管理器或Spring MVC,你就被"鎖定"在這些API中了。

◆Spring應用程式需要知道背景的服務提供者。例如,對于資料持續(data persistence)服務來說,Spring架構元件為JDBC、Hibernate、iBatis和JDO使用了不同的DAO和模闆輔助類。是以,如果你希望為Spring應用程式更換持續服務提供者(例如從JDBC切換到Hibernate),你就必須重構自己的應用程式代碼,使用新的輔助類。

服務內建

從較高的層次看,Spring架構元件位于應用程式伺服器和服務類庫之上。其服務內建代碼(例如資料通路模闆和輔助類)位于架構元件之中,并暴露給應用程式開發者。與此不同的是,EJB 3.0架構元件被緊密地內建到應用程式伺服器中,服務內建代碼被封裝在标準的接口中。

其結果是,EJB 3.0廠商可以積極地優化總體性能和開發者體驗。例如,在JBoss的 EJB 3.0實作中,使用EntityManager保持實體Bean POJO的時候,下層Hibernate對話事務會自動地與該調用方法的JTA事務聯系在一起,當JTA事務送出的時候,它也會送出。如果使用簡單的@PersistenceContext注釋(本文後面有一個例子),你甚至于可以在有狀态的(stateful)對話bean中把EntityManager和它的下層Hibernate事務捆綁到一個應用程式事務上。該應用程式事務在一個對話中跨越了多個線程,它在事務性的Web應用程式(例如多頁面購物車)中是非常有效的。由于在JBoss中,EJB 3.0架構元件、Hibernate和Tomcat緊密內建,上述的簡單和內建的程式設計接口才得以實作。Oracle的EJB 3.0架構元件和其下層Toplink持續服務之間的也實作了類似層次的內建。

EJB 3.0中內建服務的另一個例子是群集(clustering)支援。如果你在伺服器群集中部署EJB 3.0應用程式,那麼所有的失效接續(fail-over)、負載均衡、分布式緩存和狀态複制服務都是可以自動地供應用程式使用的。下層群集服務都隐藏在EJB 3.0程式設計接口後面,它們對于EJB 3.0開發人員來說是完全透明的。

在Spring中,優化架構元件與服務之間的互動操作要困難得多。例如,為了使用Spring的宣告式事務服務來管理Hibernate事務,你必須在XML配置檔案中顯式地配置Spring TransactionManager和Hibernate SessionFactory對象。Spring應用程式開發者必須顯式地管理跨多個HTTP請求的事務。此外,要在Spring應用程式中使用群集服務也沒有簡單的途徑。

服務內建的靈活性

由于Spring中的服務內建代碼是作為程式設計接口的一部分暴露的,應用程式開發者可以根據需要靈活地內建服務。這個特性允許你內建自己的"輕量級"應用程式伺服器。Spring最普遍的使用方式是把Tomcat和Hibernate"粘合"在一起來提供簡單的資料庫驅動web應用程式。在這種情況下,Spring自身提供事務服務,Hibernate提供持續(persistence)服務--這種組織方式在Spring中建立了一個微型應用程式伺服器。

EJB 3.0應用程式伺服器沒有賦予你挑選服務的靈活性。在大多數情況中,你得到一組事先包裝好的特性,而你隻需要其中的一部分。但是,如果應用程式伺服器由模式化的内部設計主導(類似JBoss),那麼你就可能把它分開,去掉一些不必要的特性。在任何情況下,定制成熟的應用程式伺服器都不是一個簡單的事情。

當然,如果應用程式的範圍超越了單節點,那麼你可能需要捆綁來自普通應用程式伺服器的服務(例如資源緩沖池、消息隊列和群集)。在總體的資源消耗方面,Spring解決方案與任何EJB 3.0解決方案一樣,都是"重量級"的。

在Spring中,靈活的服務內建使得我們更容易把仿制(mock)對象(而不是實際的服務對象)捆綁到應用程式,用于在容器外部進行單元測試。在EJB 3.0應用程式中,大多數元件都是簡單的POJO,我們可以很容易地在容器外部測試這些它們。但是對于測試那些涉及到容器服務的對象(例如持續EntityManager),我們推薦在容器内測試,因為比起仿制對象的方法,它們更簡單、更牢固、更精确。 XML與注釋的比較

從應用程式開發者的角度來看,Spring的程式設計接口主要是基于XML配置檔案的,而EJB 3.0廣泛使用了Java注釋。XML檔案可以表達複雜的關系,但是它們同時也很冗長、牢固程度也較低。注釋簡單明了,但是在注釋中我們卻很難表達複雜的或層次的結構。

Spring和EJB 3.0關于XML或注釋的選擇是依賴于這兩個架構元件後面的架構的:由于注釋隻能儲存相當少的配置資訊,隻有預先內建的架構元件(類似在架構元件中已經完成了大多數預備工作)可以廣泛地把注釋作為配置選項。我們已經讨論過了,EJB 3.0符合這種需求,而Spring作為一個通用的DI架構元件,不符合這個需求。

當然,EJB 3.0和Spring都在學習對方的最佳特性,它們都在某個程度上支援XML和注釋。例如,在EJB 3.0中XML配置檔案是一個可選的重載機制,可以用于改變注釋的預設行為。注釋也可以用于配置某些Spring服務。

繼續閱讀