摘要:
Spring框架雖然很流行但并不是一個(gè)標(biāo)準(zhǔn)的開源框架。EJB3.0是由Java Community Process (JCP)制訂的標(biāo)準(zhǔn)框架.這兩個(gè)框架結(jié)構(gòu)都有一個(gè)共同核心設(shè)計(jì)理念:將中間件服務(wù)傳遞給耦合松散的POJOS (Plain Old Java Objects, 簡(jiǎn)單潔凈Java對(duì)象)。 本文將對(duì)Srping和EJB3.0框架背后的關(guān)鍵不同處進(jìn)行考察,并討論其優(yōu)缺點(diǎn)。本文的觀點(diǎn)也適用于其它更少為人知的框架,因?yàn)樗麄兌际菍?duì)“耦合松散的POJO”的設(shè)計(jì)版權(quán)聲明:可以任意轉(zhuǎn)載,轉(zhuǎn)載時(shí)請(qǐng)務(wù)必以超鏈接形式標(biāo)明文章原始出處和作者信息及本聲明
英文原文地址:
http://www.onjava.com/pub/a/onjava/2005/06/29/spring-ejb3.html
中文地址:
http://www.matrix.org.cn/resource/article/43/43718_Spring_EJB.html
關(guān)鍵詞: Spring EJB
艾伯特.愛因斯坦曾經(jīng)說過:“一切都應(yīng)該盡可能地簡(jiǎn)單,但是不能更簡(jiǎn)單。”確實(shí)如此,簡(jiǎn)化一門理論的基本假設(shè),使我們可以專注于真正關(guān)鍵的地方,這正是一直以來對(duì)科學(xué)真理的追求。企業(yè)軟件開發(fā)同樣如此。
提供一個(gè)將復(fù)雜的事物(例如,事務(wù)、安全或持久性)對(duì)開發(fā)者進(jìn)行隱藏的應(yīng)用框架是簡(jiǎn)化企業(yè)軟件開發(fā)的關(guān)鍵。一個(gè)設(shè)計(jì)良好的框架可以提高代碼重用率、開發(fā)者的生產(chǎn)力及軟件的質(zhì)量。然而,現(xiàn)有J2EE1.4的EJB2.1框架被普遍認(rèn)為設(shè)計(jì)差,且過于復(fù)雜。不滿于EJB2.1的框架結(jié)構(gòu),Java開發(fā)者嘗試了各種各樣的中間件服務(wù)傳遞方法。最引人注目的是,以下兩個(gè)框架引起了開發(fā)者極大興趣并得到了大量正面的反饋。他們以未來企業(yè)Java應(yīng)用所選框架的姿態(tài)展現(xiàn)。
????????Spring框架雖然很流行但并不是一個(gè)標(biāo)準(zhǔn)的開源框架。它主要由Interface21 Inc開發(fā)和控制。Spring框架結(jié)構(gòu)是基于依賴注入(Dependency Injection (DI))的設(shè)計(jì)模式。它可以獨(dú)立或在現(xiàn)有的應(yīng)用服務(wù)器上運(yùn)行,而且大量地使用了xml配置文件
????????EJB3.0是由Java Community Process (JCP)制訂的標(biāo)準(zhǔn)框架,為所有主要的J2EE廠商支持。JBoss已經(jīng)提供了試用版EJB3.0標(biāo)準(zhǔn)的開源或商業(yè)性質(zhì)實(shí)現(xiàn)。EJB3.0充分利用了Java的注釋
這兩個(gè)框架結(jié)構(gòu)都有一個(gè)共同核心設(shè)計(jì)理念:將中間件服務(wù)傳遞給耦合松散的POJOS (Plain Old Java Objects, 簡(jiǎn)單潔凈Java對(duì)象)。 這樣的框架利用截取執(zhí)行上下文或在運(yùn)行時(shí)將服務(wù)對(duì)象注入POJO來把應(yīng)用服務(wù)“纏繞”到POJO。POJO本身并不關(guān)心這種“纏繞”,對(duì)這種框架結(jié)構(gòu)也沒有什么依賴。因此,開發(fā)者可專注于業(yè)務(wù)邏輯和脫離框架的POJO單元測(cè)試。除此之外, 由于POJO并不須要繼承框架的類或?qū)崿F(xiàn)其接口,開發(fā)者能夠極其靈活地搭建繼承結(jié)構(gòu)和建造應(yīng)用。
然而,在擁有同一理念的同時(shí),兩個(gè)框架結(jié)構(gòu)使用不同的方式來傳遞POJO服務(wù)。許多書籍或文章都將Spring 或EJB3.0和EJB2.1做了比較,但是對(duì)Spring 和EJB3.0的比較并沒有仔細(xì)研究過。在本文中,我將對(duì)Srping和EJB3.0框架背后的關(guān)鍵不同處進(jìn)行考察,并討論其優(yōu)缺點(diǎn)。本文的觀點(diǎn)也適用于其它更少為人知的框架,因?yàn)樗麄兌际菍?duì)“耦合松散的POJO”的設(shè)計(jì)。希望這篇文章可以幫助你選擇適合你需求的最好框架。
廠商無關(guān)性
開發(fā)者選擇Java平臺(tái)其中最引人注目的理由之一:廠商無關(guān)性。EJB3.0正是一套設(shè)計(jì)為廠商無關(guān)的開放性標(biāo)準(zhǔn)。EJB3.0標(biāo)準(zhǔn)為所有企業(yè)Java社團(tuán)里開源或商業(yè)性質(zhì)廠商所開發(fā)和支持。它將開發(fā)者與應(yīng)用服務(wù)器實(shí)現(xiàn)完全隔離。例如,JBoss的 EJB3.0實(shí)現(xiàn)基于Hibernate,Oracle的基于TopLink,但是開發(fā)者并不須要學(xué)習(xí)Hibernate- 或TopLink的具體API來使應(yīng)用可在Jboss或Oracle上運(yùn)行。廠商無關(guān)性使EJB3.0與現(xiàn)今其它POJO中間件框架區(qū)別開來。
但是,正如許多EJB3.0評(píng)論家迅速所指出的,在本文撰寫時(shí)EJB3.0標(biāo)準(zhǔn)還沒有到達(dá)一個(gè)最終版本。大概還有一到兩年的時(shí)間EJB3.0才能廣泛地為所有主要J2EE廠商所支持。即使你的應(yīng)用服務(wù)器本身不支持EJB3.0,你仍然可以通過下載安裝”內(nèi)嵌的”EJB3.0產(chǎn)品來運(yùn)行EJB3.0的應(yīng)用。例如,JBoss的內(nèi)嵌EjB3.0是開源產(chǎn)品且可以在任何J2SE5.0兼容的環(huán)境運(yùn)行(例如, 在任何Java服務(wù)器上),此產(chǎn)品正處于軟件測(cè)試階段。其它廠商不久也將發(fā)布自己的內(nèi)嵌EJB3.0產(chǎn)品,特別是針對(duì)標(biāo)準(zhǔn)中關(guān)于數(shù)據(jù)持久性的部分。
另一方面,Spring一直以來都是非標(biāo)準(zhǔn)的技術(shù),在未來可預(yù)知的一段時(shí)間內(nèi)這種情況將持續(xù)下去。雖然你可以在任何應(yīng)用服務(wù)器上使用Spring框架,Spring應(yīng)用會(huì)被鎖入在Spring本身和你選擇整合進(jìn)Spring的具體服務(wù)中。
????????Spring框架是一個(gè)開源項(xiàng)目,但同時(shí)它有一個(gè)XML格式的配置文件和編程接口。當(dāng)然任何一個(gè)非標(biāo)準(zhǔn)的產(chǎn)品都會(huì)有這種“鎖入”(lock-in)的情況,并不是Spring特有的。但Spring應(yīng)用的長期生存能力仍然還得托Spring這個(gè)項(xiàng)目的福(或者是Interface21公司,它雇傭了大部分Spring核心開發(fā)人員)。除此之外,假如你用到任何一個(gè)具體的Spring服務(wù),例如,Spring事務(wù)管理器或則Spring MVC,你也會(huì)被鎖入到這些API里。
????????Spring的應(yīng)用對(duì)終端用戶是不可知的。例如,對(duì)數(shù)據(jù)持久服務(wù),Spring框架兼容不同的DAO和JDBC的模版幫助類,如Hibernate, iBatis, 和 JDO。所以假如你需要為spring應(yīng)用切換在數(shù)據(jù)持久化服務(wù)(例如從JBDC到Hibernate),你需要修改你的代碼以適合新的模版幫助類。
服務(wù)整合
從一個(gè)很高的角度上看,Spring框架處于應(yīng)用服務(wù)器和服務(wù)庫的上方。服務(wù)整合的代碼(如,數(shù)據(jù)訪問模板和幫助類)屬于框架,并暴露于應(yīng)用開發(fā)者。相反,EJB3.0框架與應(yīng)用服務(wù)器高度整合,服務(wù)整合代碼也包裝在一個(gè)標(biāo)準(zhǔn)接口后面。
因此,實(shí)現(xiàn)EJB3.0的廠商可以大大地優(yōu)化整體性能和提升開發(fā)者的體驗(yàn)。例如,在JBoss EJB3.0的實(shí)現(xiàn)中,當(dāng)你在用EntityManager持久化一個(gè)Entity Bean時(shí),后臺(tái)的Hibernate會(huì)話事務(wù)已經(jīng)自動(dòng)地幫定到調(diào)用方法的JTA 的事務(wù)上,在JTA 事務(wù)提交的同時(shí)Hibernate會(huì)話事務(wù)也提交了。你甚至可以使用一個(gè)簡(jiǎn)單的 @PersistenceContext 注釋(稍候例子演示)將EntityManager和它后臺(tái)的Hibernate事務(wù)綁定到一個(gè)stateful session bean的應(yīng)用事務(wù)中。在一個(gè)會(huì)話中應(yīng)用事務(wù)橫跨多個(gè)線程,這在事務(wù)性網(wǎng)頁應(yīng)用很有用,例如,多頁面的購物車。
由于高度整合的EJB3.0的框架,使簡(jiǎn)單、集成的編程接口成為可能。Oracle EJB3.0框架和其后臺(tái)的Toplink持久化服務(wù)也同樣程度地整合。
另一個(gè)EJB3.0整合服務(wù)的絕好例子就是集群支持。假如你在一個(gè)服務(wù)器集群上部署了一個(gè)EJB3.0的應(yīng)用,所有容錯(cuò)(fail-over)、負(fù)載均衡、分布式緩沖和狀態(tài)復(fù)制都已經(jīng)自動(dòng)為應(yīng)用所獲得可用。后臺(tái)的集群支持被隱藏在EJB3.0的框架后面,對(duì)EJB3.0開發(fā)者來說這些都是完全透明不可見的。
在Spring里,很難優(yōu)化框架和服務(wù)之間的通訊。例如,為了使用Spring里的聲明事務(wù)服務(wù)來管理Hibernate事務(wù),你必須顯示地在XML文件中配置Spring TransactionManager和Hibernate SessionFactory對(duì)象。Spring必須電顯示地管理橫跨多個(gè)HTTP請(qǐng)求的事務(wù)。除此之外,沒有別的方法均衡Spring應(yīng)用里的集群。
服務(wù)組合的彈性
由于Spring的服務(wù)整合代碼作為編程接口的一部份暴露在外,應(yīng)用開發(fā)者有按自己需求裝配服務(wù)的彈性。這個(gè)特點(diǎn)使你能夠組合自己的輕量級(jí)應(yīng)用服務(wù)器。Spring的一個(gè)普遍用法就是將Tomcat和Hibernate組合在一起支持?jǐn)?shù)據(jù)庫驅(qū)動(dòng)的web應(yīng)用。在這種情況,Spring本身提供事務(wù)服務(wù),Hibernat提供持久化服務(wù)——這種設(shè)置創(chuàng)建了一個(gè)袖珍型的應(yīng)用服務(wù)器。
EJB3.0應(yīng)用服務(wù)器典型地不提供這種根據(jù)需求任你挑撿服務(wù)的彈性空間。大多數(shù)時(shí)間,你得到的只是一系列包裝好的特性,其中一些你可能根本就不需要。但是如果應(yīng)用服務(wù)器像JBoss一樣提供一個(gè)模塊性的內(nèi)部設(shè)計(jì),那么你可以只取其中一部分,而把不必要的部分剝?nèi)ァT谌魏吻闆r,去自定義一個(gè)功能強(qiáng)大的應(yīng)用服務(wù)器是沒有什么價(jià)值的。
當(dāng)然,假如應(yīng)用已經(jīng)超過單個(gè)點(diǎn),那么你應(yīng)該加入常用服務(wù)器上的服務(wù),例如,資源池(resource pooling),消息隊(duì)列(message queuing)和集群(clustering)。就總體的資源消耗而言,Spring解決方法和其他EJB3.0解決方法一樣是重量級(jí)的。
在Spring框架里,具有彈性的服務(wù)裝配使得將虛擬對(duì)象而不是真正的業(yè)務(wù)對(duì)象綁定到應(yīng)用中做脫離容器的單元測(cè)試更簡(jiǎn)單。在EJB3.0應(yīng)用中,大多數(shù)組件都是簡(jiǎn)單POJO,他們可以很容易地在容器外被測(cè)試。但是對(duì)于與容器服務(wù)相關(guān)的對(duì)象(例如持久化實(shí)實(shí)體管理器EntityManager)建議用容器內(nèi)測(cè)試。因?yàn)檫@樣會(huì)比虛擬對(duì)象測(cè)試方法更簡(jiǎn)單,強(qiáng)壯及準(zhǔn)確。
XML Vs.注解
從應(yīng)用開發(fā)者的觀點(diǎn)上來看,Spring的編程開發(fā)接口主要基于XML配置文件而EJB3.0廣泛地應(yīng)用Java注解。XML可以表達(dá)復(fù)雜的關(guān)系,但是它也冗長且不夠健壯;注解簡(jiǎn)單明了,但是很難在注解里表達(dá)復(fù)雜或繼承性的關(guān)系。
Spring選擇XML或EJB3.0選擇注解都是有他們兩者框架后的體系結(jié)構(gòu)決定的。因?yàn)樽⒔庵荒苋菁{很少的配置信息,只有整合前的框架(重頭戲都在框架里)才可以把廣泛地使用注解作為配置選擇。正如我們所討論過的,EJB3.0剛好符合這個(gè)要求,而Spring作為一個(gè)普通的DI框架并不符合。
當(dāng)然,EJB3.0和Spring都相互取長補(bǔ)短,在某種程度上他們都支持XML和注解。例如,在EJB3.0中,XML配置文件作為一個(gè)可選的重載機(jī)制來改變注解的默認(rèn)行為。注解也可以配置一些Spring服務(wù)。
通過例子是學(xué)習(xí)XML和注解方式之間差異的最好方法。在下面幾個(gè)環(huán)節(jié)里,讓我們來看看Spring和EJB3.0是怎樣提供關(guān)鍵服務(wù)給應(yīng)用的。
聲明性服務(wù)
Spring和EJB3.0都將運(yùn)行時(shí)服務(wù)(例如,事務(wù)、安全、日志和配置服務(wù))綁定到應(yīng)用。因?yàn)檫@些服務(wù)于應(yīng)用的業(yè)務(wù)邏輯是沒有直接聯(lián)系,他們只是由應(yīng)用本身管理。換句話說,這些服務(wù)在運(yùn)行時(shí)由容器透明地應(yīng)用到應(yīng)用中。開發(fā)者或是管理者配置容器,準(zhǔn)確地告訴它什么時(shí)候怎樣應(yīng)用這些服務(wù)。
EJB3.0運(yùn)用Java注解來配置聲明性服務(wù),而Sring使用XML配置文件。在大多數(shù)情況下,EJB3.0注解方式對(duì)于這種服務(wù)更簡(jiǎn)單明了。這里有一個(gè)在EJB3.0中將事務(wù)服務(wù)運(yùn)用到POJO的例子。
public class Foo {
????
????@TransactionAttribute(TransactionAttributeType.REQUIRED)
????public bar () {
??????// do something ...
????}????
}
你也可以為一個(gè)代碼段聲明多個(gè)屬性,應(yīng)用多個(gè)服務(wù)。這是一個(gè)在EJB3.0里同時(shí)應(yīng)用事務(wù)和安全服務(wù)到POJO的例子。
@SecurityDomain("other")
public class Foo {
????
????@RolesAllowed({"managers"})
????@TransactionAttribute(TransactionAttributeType.REQUIRED)
????public bar () {
??????// do something ...
????}??
}
使用XML說明代碼屬性和配置聲明性服務(wù)會(huì)導(dǎo)致冗長和不穩(wěn)定的配置文件。下面是一個(gè)在Spring應(yīng)用中的XML片段,其應(yīng)用一個(gè)非常簡(jiǎn)單的Hibernate事務(wù)到方法Foo.bar()中。
<!-- Setup the transaction interceptor -->
<bean id="foo"
??class="org.springframework.transaction
????????.interceptor.TransactionProxyFactoryBean">
????
????<property name="target">
????????<bean class="Foo"/>
????</property>
????
????<property name="transactionManager">
????????<ref bean="transactionManager"/>
????</property>
????
????<property name="transactionAttributeSource">
????????<ref bean="attributeSource"/>
????</property>
</bean>
<!-- Setup the transaction manager for Hibernate -->
<bean id="transactionManager"
??class="org.springframework.orm
???????? .hibernate.HibernateTransactionManager">
????
????<property name="sessionFactory">
????????<!-- you need to setup the sessionFactory bean in
???????????? yet another XML element -- omitted here -->
????????<ref bean="sessionFactory"/>
????</property>
</bean>
<!-- Specify which methods to apply transaction -->
<bean id="transactionAttributeSource"
??class="org.springframework.transaction
???????? .interceptor.NameMatchTransactionAttributeSource">
??
????<property name="properties">
????????<props>
????????????<prop key="bar">
????????</props>
????</property>
</bean>
XML的復(fù)雜度會(huì)以幾何級(jí)數(shù)增長,如果你向同一個(gè)POJO添加更多的攔截器(interceptors)(例如安全攔截器)。意識(shí)到只有XML配置文件的局限,Spring使用Apache Commons 元數(shù)據(jù)在Java源碼中來說明事務(wù)屬性。最新版本的Spring1.2也支持JDK-1.5風(fēng)格注解。要使用事務(wù)元數(shù)據(jù),你須要將上面的transactionAttributeSourc bean變成一個(gè)AttributesTransactionAttributeSource實(shí)例。并為元數(shù)據(jù)攔截器添加額外邦定。
????class="org.springframework.aop.framework.autoproxy
?????????? .DefaultAdvisorAutoProxyCreator"/>
<bean id="transactionAttributeSource"
????class="org.springframework.transaction.interceptor
?????????? .AttributesTransactionAttributeSource"
????autowire="constructor"/>
<bean id="transactionInterceptor"
????class="org.springframework.transaction.interceptor
?????????? .TransactionInterceptor"
????autowire="byType"/>
<bean id="transactionAdvisor"
????class="org.springframework.transaction.interceptor
?????????? .TransactionAttributeSourceAdvisor"
????autowire="constructor"/>
<bean id="attributes"
????class="org.springframework.metadata.commons
?????????? .CommonsAttributes"/>
當(dāng)你有很多事務(wù)性方法時(shí),Spring元數(shù)據(jù)可以簡(jiǎn)化transactionAttributeSource。但是這并沒有解決XML配置文件的根本問題。冗長而又繁瑣的事務(wù)攔截器, transactionManager,和transactionAttributeSource仍然需要。
依賴注入(Dependency Injection, DI)
中間件容器的一個(gè)關(guān)鍵好處之一就是它可以讓開發(fā)者建造一個(gè)關(guān)系耦合松散的應(yīng)用。服務(wù)端客戶只需要知道服務(wù)的接口。容器依據(jù)具體的實(shí)現(xiàn)實(shí)例化服務(wù)對(duì)象,使他們?yōu)榭蛻舳怂谩T诓桓淖兘涌诤涂蛻舳舜a的情況下,這使得容器可以在多種服務(wù)實(shí)現(xiàn)之間切換。
依賴注入的模式是實(shí)現(xiàn)耦合松散應(yīng)用的最好方法之一。它更易用,比其他方法也明了多了,比如通過JNDI依賴性查詢或容器回調(diào)。使用DI,框架就像一個(gè)對(duì)象工廠,它創(chuàng)建服務(wù)對(duì)象然后按照運(yùn)行時(shí)配置將這些服務(wù)對(duì)象注入到應(yīng)用的POJO里。站在應(yīng)用開發(fā)者的角度,客戶端POJO在被使用時(shí)可自動(dòng)獲得正確的服務(wù)對(duì)象。
Spring和EJB3.0都提供廣泛的DI模式支持。但是他們之間仍存在很大的不同之處。Spring支持一般意義上且復(fù)雜的DI API,其基于XML配置文件。EJB3.0支持大多數(shù)普通服務(wù)對(duì)象(如EJB及context對(duì)象)的注入和任何簡(jiǎn)單注解的JDNI。
EJB63.0注解非常簡(jiǎn)單易用。@Resource 標(biāo)記表示注入大多數(shù)普通服務(wù)對(duì)象和JDNI對(duì)象。以下例子展示了怎樣把服務(wù)的JDNI的默認(rèn)DataSource 對(duì)象注入到POJO的一個(gè)屬性變量中。DefaultDS是DataSource.的JDNI名字。MyDb變量在第一次被使用時(shí)被賦上了正確的值。
public class FooDao {
????@Resource (name="DefaultDS")
????DataSource myDb;
????
????// Use myDb to get JDBC connection to the database
}
除了直接屬性變量注入,Ejb3.0的@Resource注解也可以用來在setter方法里面注入對(duì)象。例如,下面的例子就是注入session context對(duì)象。應(yīng)用從不會(huì)顯示地調(diào)用setter方法,其在其他方法被調(diào)用前由容器來觸發(fā)。
@Resource
public void setSessionContext (SessionContext ctx) {
????sessionCtx = ctx;
}
針對(duì)更復(fù)雜的服務(wù)對(duì)象,定義了專用的注入注解。例如,@EJB注釋用來注入EJB的Stub,@PersistenceContext注解用來注入處理EJB3.0實(shí)體bean訪問數(shù)據(jù)庫的EntityManager對(duì)象。下面是一個(gè)怎樣將EntityManager對(duì)象注入有狀態(tài)的 session bean的例子。@PersistenceContext的type屬性具體說明了被注入的EntityManager有一個(gè)擴(kuò)展的事務(wù)transaction context。transaction context并不會(huì)同JTA transaction manager一起自動(dòng)提交。因此它可以用在在一個(gè)會(huì)話橫跨多個(gè)線程的應(yīng)用事務(wù)中。
@Stateful
public class FooBean implements Foo, Serializable {
????@PersistenceContext(
??????type=PersistenceContextType.EXTENDED
????)
????protected EntityManager em;
????
????public Foo getFoo (Integer id) {
????????return (Foo) em.find(Foo.class, id);
????}
}
EJB3.0標(biāo)準(zhǔn)通過注解可以被注入的服務(wù)器資源。但是它并支持將用戶定義的應(yīng)用POJO之間的相互注入。
在Spring中,首先你必須為POJO中的服務(wù)對(duì)象定義一個(gè)setter方法。下面的例子說明POJO需要一個(gè)Hibernate session 的引用
public class FooDao {
????
????HibernateTemplate hibernateTemplate;
????
????public void setHibernateTemplate (HibernateTemplate ht) {
????????hibernateTemplate = ht;
????}
????
????// Use hibernateTemplate to access data via Hibernate
????public Foo getFoo (Integer id) {
????????return (Foo) hibernateTemplate.load (Foo.class, id);
????}
}
然后,以XML里的元素作為橋梁具體描述容器怎樣在運(yùn)行時(shí)得到服務(wù)對(duì)象并將其注入到POJO里。以下是一個(gè)XML例子,具體描述了將一個(gè)數(shù)據(jù)源綁定到一個(gè)Hibernate session factory,然后從Hibernate session factory到Hibernate template object,最后從template object到應(yīng)用的POJO。Spring代碼如此復(fù)雜的部分原因是因?yàn)槲覀冺毷质謩?dòng)注入后臺(tái)Hibernate plumbing objects。而EJB3.0 EntityManager是自動(dòng)被服務(wù)器管理和配置。這又將我們帶回到Spring并不像EJB3.0那樣高度與服務(wù)整合的論點(diǎn)上。
<bean id="dataSource"
??class="org.springframework
???????? .jndi.JndiObjectFactoryBean">
????<property name="jndiname">
????????<value>java:comp/env/jdbc/MyDataSource</value>
????</property>
</bean>
<bean id="sessionFactory"
??class="org.springframework.orm
???????? .hibernate.LocalSessionFactoryBean">
????<property name="dataSource">
????????<ref bean="dataSource"/>
????</property>
</bean>
<bean id="hibernateTemplate"
??class="org.springframework.orm
???????? .hibernate.HibernateTemplate">
????<property name="sessionFactory">
????????<ref bean="sessionFactory"/>
????</property>????
</bean>
<bean id="fooDao" class="FooDao">
????<property name="hibernateTemplate">
????????<ref bean="hibernateTemplate"/>
????</property>
</bean>
<!-- The hibernateTemplate can be injected
????????into more DAO objects -->
雖然,Spring里基于XML的依賴注入語法復(fù)雜,但卻功能強(qiáng)大。你可以將任何POJO注入到另一個(gè)POJO,包括你自己在應(yīng)用定義的那些POJO。假如你想在EJB3.0應(yīng)用中用Spring的DI功能 ,你可以通過JNDI把一個(gè)Spring bean factory注入到EJB。在一些EJB3.0的應(yīng)用服務(wù)器里,廠商可能會(huì)額外定義非標(biāo)準(zhǔn)的POJO注入API。一個(gè)很好的例子就是JBoss MicroContainer。它比Spring更一般化,因?yàn)樗幚鞟spect-Oriented Programming(AOP)的依賴。
結(jié)論
Spring和Ejb3.0雖然都是為了向企業(yè)服務(wù)提供耦合松散的POJO,但是使用了不同方法來達(dá)到這個(gè)目的。兩者都大量地使用了依賴注入。
對(duì)于EJB3.0,基于標(biāo)準(zhǔn)的方案、注解的廣泛使用、與應(yīng)用服務(wù)器的高度整合都使得EJB3.0擁有更好的廠商無關(guān)性,更高的開發(fā)效率。依賴注入和集中的XML配置文件協(xié)調(diào)一致的使用使開發(fā)者能夠構(gòu)建更有彈性的應(yīng)用,并且可以同時(shí)和幾個(gè)應(yīng)用服務(wù)提供者一起協(xié)作。
鳴謝
作者感謝tephen Chambers,、ill Burke、Andy Oliver的珍貴意見。
資源
Spring框架(參見CodeZoo: Spring)
EJB 3.0
JBoss EJB 3.0
Oracle Application Server EJB 3.0 Preview
Michael Juntao Yuan 善長于提供end-to-end的企業(yè)解決方案, 也是一個(gè)移動(dòng)方面的專家,是avid這個(gè)開源項(xiàng)目的支持者。