常言笑的家

          Spring, Hibernate, Struts, Ajax, RoR

          POJO應(yīng)用架構(gòu):Spring與EJB 3.0的對比

                 
                 愛因斯坦曾經(jīng)說過:"每件事物都應(yīng)該盡可能簡單,而不是更簡單"。的確,對科學(xué)真理的追求都是為了簡化理論的根本假設(shè),這樣我們才能處理真正麻煩的問題。企業(yè)級軟件的開發(fā)也是這樣的。

            簡化企業(yè)級軟件開發(fā)的關(guān)鍵是提供一個(gè)隱藏了復(fù)雜性(例如事務(wù)、安全性和永續(xù)性)的應(yīng)用框架。良好設(shè)計(jì)的框架組件可以提升代碼的重復(fù)使用(reuse)能力,提高開發(fā)效率,從而得到更好的軟件質(zhì)量。但是,目前J2EE 1.4中的EJB 2.1框架組件被人們普遍認(rèn)為是設(shè)計(jì)較差的和過于復(fù)雜的。Java開發(fā)者對EJB 2.1很不滿,他們已經(jīng)試驗(yàn)了多種其它的用于中間件服務(wù)傳送的方法。最引人注目的,下面兩個(gè)框架組件已經(jīng)引起開發(fā)者的巨大興趣和積極的反映。它們很可能成為未來企業(yè)級Java應(yīng)用程序可供選擇的框架組件。

            · Spring框架組件是一個(gè)流行的,但是非標(biāo)準(zhǔn)的開放源代碼框架組件。它主要是由Interface21 Inc.公司開發(fā)和控制的。Spring框架組件的架構(gòu)是基于依賴注入(DI)設(shè)計(jì)模式的。Spring可以單獨(dú)地或者與現(xiàn)有的應(yīng)用程序服務(wù)器一起工作,它大量地使用XML配置文件。

            · EJB 3.0框架組件是一個(gè)標(biāo)準(zhǔn)的框架組件,由Java社區(qū)組織(JCP)定義,并受到所有主流的J2EE廠商支持。預(yù)發(fā)布的EJB 3.0規(guī)范的開放源代碼和商業(yè)實(shí)現(xiàn)都可以在JBoss和Oracle上看到了。EJB 3.0大量使用Java注釋(annotation)。

            這兩個(gè)框架組件的核心設(shè)計(jì)理念是相同的:兩者的目標(biāo)都是把中間件服務(wù)傳遞給松散耦合的簡單舊式Java對象(POJO)。這些框架組件通過在運(yùn)行時(shí)截取執(zhí)行內(nèi)容或向POJO注入服務(wù)對象,把應(yīng)用程序服務(wù)與POJO捆綁在一起。POJO本身不關(guān)心捆綁的過程,并且對框架組件幾乎沒有依賴。其結(jié)果是,開發(fā)者可以聚焦于業(yè)務(wù)邏輯,個(gè)人可以在沒有框架組件的情況下測試他們的POJO。此外,由于POJO不需要從框架組件中繼承或?qū)崿F(xiàn)框架組件接口,開發(fā)者建立繼承結(jié)構(gòu)和構(gòu)建應(yīng)用程序的時(shí)候都有高度的靈活性。

            但是,盡管兩者的設(shè)計(jì)理念是相同的,它們傳遞POJO服務(wù)時(shí)卻采用了完全不同的方法。盡管目前已經(jīng)出版了大量的圖書和文章來把Spring或EJB 3.0與EJB 2.1進(jìn)行對比,但是它們都沒有對Spring與EJB 3.0之間的差異進(jìn)行認(rèn)真的研究。在本文中,我將研究Spring和EJB 3.0框架組件之間的關(guān)鍵差異,并討論它們的優(yōu)缺點(diǎn)。本文的主題也可以應(yīng)用在其它一些名氣稍小的企業(yè)級中間件框架組件上,因?yàn)樗鼈兌季劢褂?松散耦合的POJO"設(shè)計(jì)。我希望本文能夠幫助你選擇符合需求的最佳的框架組件。

            廠商無關(guān)性(Independence)

            開發(fā)者選擇某種Java平臺的一個(gè)最重要的理由就是該平臺的廠商無關(guān)性。EJB 3.0是一個(gè)開放的、標(biāo)準(zhǔn)的、具有廠商無關(guān)性的平臺。EJB 3.0規(guī)范是由企業(yè)級Java團(tuán)體中所有主流開放源代碼和商業(yè)廠商開發(fā)和支持的。EJB 3.0框架組件把開發(fā)人員與應(yīng)用程序服務(wù)器實(shí)現(xiàn)(implementation)隔離開來了。例如,盡管JBoss的EJB 3.0實(shí)現(xiàn)是基于Hibernate的,而Oracle的EJB 3.0實(shí)現(xiàn)是基于TopLink的,但是開發(fā)人員并不需要學(xué)習(xí)Hibernate或TopLink的特殊API,就可以讓他們的應(yīng)用程序在JBoss和Oracle上運(yùn)行。廠商無關(guān)性把EJB 3.0框架組件與其它的POJO中間件框架組件區(qū)分開來了。

            但是,很多EJB 3.0的批評家迅速指出,在寫這篇文章的時(shí)候,EJB 3.0規(guī)范還沒有達(dá)到最終發(fā)表的版本。在EJB 3.0被所有主流的J2EE廠商采用之前可能還需要一到兩年時(shí)間。但是,即使你的應(yīng)用程序服務(wù)器還沒有自然地(natively)支持EJB 3.0,你還是可以通過下載和安裝一個(gè)"嵌入式的" EJB 3.0產(chǎn)品,在服務(wù)器上運(yùn)行EJB 3.0應(yīng)用程序。例如,JBoss嵌入式EJB 3.0產(chǎn)品是開放源代碼的,可以在任何與J2SE-5.0兼容的環(huán)境中(例如,在Java應(yīng)用程序服務(wù)器中)運(yùn)行。它現(xiàn)在正在進(jìn)行beta測試。其它的廠商也可能很快發(fā)布他們的嵌入式EJB 3.0產(chǎn)品,特別是用于規(guī)范的"數(shù)據(jù)永續(xù)性"部分的產(chǎn)品。

            另一方面,Spring一直是非標(biāo)準(zhǔn)的技術(shù),而且在可以預(yù)見的未來它仍然是這樣的。盡管你可以把Spring框架組件與任何應(yīng)用程序服務(wù)器一起使用,但是Spring應(yīng)用程序都被"鎖定"在Spring自身和你所選擇的集成到Spring中的特定服務(wù)中了。

            · 盡管Spring框架組件是一個(gè)開放源代碼項(xiàng)目,但是它仍然擁有配置文件的專利XML格式和專利編程接口。當(dāng)然,這類"鎖定"發(fā)生在任何非標(biāo)準(zhǔn)的產(chǎn)品上,Spring也不例外。但是它卻造成了:你的Spring應(yīng)用程序的長期生存能力依賴于Spring項(xiàng)目本身(或Interface21 Inc公司,它雇傭了大多數(shù)Spring核心開放人員)。此外,如果你使用任何Spring特定的服務(wù),例如Spring事務(wù)管理器或Spring MVC,你就被"鎖定"在這些API中了。

            · Spring應(yīng)用程序需要知道后臺的服務(wù)提供者。例如,對于數(shù)據(jù)持續(xù)(data persistence)服務(wù)來說,Spring框架組件為JDBC、Hibernate、iBatis和JDO使用了不同的DAO和模板輔助類。因此,如果你希望為Spring應(yīng)用程序更換持續(xù)服務(wù)提供者(例如從JDBC切換到Hibernate),你就必須重構(gòu)自己的應(yīng)用程序代碼,使用新的輔助類。

            服務(wù)集成

            從較高的層次看,Spring框架組件位于應(yīng)用程序服務(wù)器和服務(wù)類庫之上。其服務(wù)集成代碼(例如數(shù)據(jù)訪問模板和輔助類)位于框架組件之中,并暴露給應(yīng)用程序開發(fā)者。與此不同的是,EJB 3.0框架組件被緊密地集成到應(yīng)用程序服務(wù)器中,服務(wù)集成代碼被封裝在標(biāo)準(zhǔn)的接口中。

            其結(jié)果是,EJB 3.0廠商可以積極地優(yōu)化總體性能和開發(fā)者體驗(yàn)。例如,在JBoss的 EJB 3.0實(shí)現(xiàn)中,使用EntityManager保持實(shí)體BeanPOJO的時(shí)候,下層Hibernate對話事務(wù)會自動地與該調(diào)用方法的JTA事務(wù)聯(lián)系在一起,當(dāng)JTA事務(wù)提交的時(shí)候,它也會提交。如果使用簡單的@PersistenceContext注釋(本文后面有一個(gè)例子),你甚至于可以在有狀態(tài)的(stateful)對話bean中把EntityManager和它的下層Hibernate事務(wù)捆綁到一個(gè)應(yīng)用程序事務(wù)上。該應(yīng)用程序事務(wù)在一個(gè)對話中跨越了多個(gè)線程,它在事務(wù)性的Web應(yīng)用程序(例如多頁面購物車)中是非常有效的。由于在JBoss中,EJB 3.0框架組件、Hibernate和Tomcat緊密集成,上述的簡單和集成的編程接口才得以實(shí)現(xiàn)。Oracle的EJB 3.0框架組件和其下層Toplink持續(xù)服務(wù)之間的也實(shí)現(xiàn)了類似層次的集成。

            EJB 3.0中集成服務(wù)的另一個(gè)例子是群集(clustering)支持。如果你在服務(wù)器群集中部署EJB 3.0應(yīng)用程序,那么所有的失效接續(xù)(fail-over)、負(fù)載均衡、分布式緩存和狀態(tài)復(fù)制服務(wù)都是可以自動地供應(yīng)用程序使用的。下層群集服務(wù)都隱藏在EJB 3.0編程接口后面,它們對于EJB 3.0開發(fā)人員來說是完全透明的。

            在Spring中,優(yōu)化框架組件與服務(wù)之間的交互操作要困難得多。例如,為了使用Spring的宣告式事務(wù)服務(wù)來管理Hibernate事務(wù),你必須在XML配置文件中顯式地配置Spring TransactionManager和Hibernate SessionFactory對象。Spring應(yīng)用程序開發(fā)者必須顯式地管理跨多個(gè)HTTP請求的事務(wù)。此外,要在Spring應(yīng)用程序中使用群集服務(wù)也沒有簡單的途徑。

            服務(wù)集成的靈活性

            由于Spring中的服務(wù)集成代碼是作為編程接口的一部分暴露的,應(yīng)用程序開發(fā)者可以根據(jù)需要靈活地集成服務(wù)。這個(gè)特性允許你集成自己的"輕量級"應(yīng)用程序服務(wù)器。Spring最普遍的使用方式是把Tomcat和Hibernate"粘合"在一起來提供簡單的數(shù)據(jù)庫驅(qū)動web應(yīng)用程序。在這種情況下,Spring自身提供事務(wù)服務(wù),Hibernate提供持續(xù)(persistence)服務(wù)--這種組織方式在Spring中建立了一個(gè)微型應(yīng)用程序服務(wù)器。

            EJB 3.0應(yīng)用程序服務(wù)器沒有賦予你挑選服務(wù)的靈活性。在大多數(shù)情況中,你得到一組事先包裝好的特性,而你只需要其中的一部分。但是,如果應(yīng)用程序服務(wù)器由模式化的內(nèi)部設(shè)計(jì)主導(dǎo)(類似JBoss),那么你就可能把它分開,去掉一些不必要的特性。在任何情況下,定制成熟的應(yīng)用程序服務(wù)器都不是一個(gè)簡單的事情。

            當(dāng)然,如果應(yīng)用程序的范圍超越了單節(jié)點(diǎn),那么你可能需要捆綁來自普通應(yīng)用程序服務(wù)器的服務(wù)(例如資源緩沖池、消息隊(duì)列和群集)。在總體的資源消耗方面,Spring解決方案與任何EJB 3.0解決方案一樣,都是"重量級"的。

            在Spring中,靈活的服務(wù)集成使得我們更容易把仿制(mock)對象(而不是實(shí)際的服務(wù)對象)捆綁到應(yīng)用程序,用于在容器外部進(jìn)行單元測試。在EJB 3.0應(yīng)用程序中,大多數(shù)組件都是簡單的POJO,我們可以很容易地在容器外部測試這些它們。但是對于測試那些涉及到容器服務(wù)的對象(例如持續(xù)EntityManager),我們推薦在容器內(nèi)測試,因?yàn)楸绕鸱轮茖ο蟮姆椒ǎ鼈兏唵巍⒏喂獭⒏_。 XML與注釋的比較
          從應(yīng)用程序開發(fā)者的角度來看,Spring的編程接口主要是基于XML配置文件的,而EJB 3.0廣泛使用了Java注釋。XML文件可以表達(dá)復(fù)雜的關(guān)系,但是它們同時(shí)也很冗長、牢固程度也較低。注釋簡單明了,但是在注釋中我們卻很難表達(dá)復(fù)雜的或?qū)哟蔚慕Y(jié)構(gòu)。

            Spring和EJB 3.0關(guān)于XML或注釋的選擇是依賴于這兩個(gè)框架組件后面的架構(gòu)的:由于注釋只能保存相當(dāng)少的配置信息,只有預(yù)先集成的框架組件(類似在框架組件中已經(jīng)完成了大多數(shù)預(yù)備工作)可以廣泛地把注釋作為配置選項(xiàng)。我們已經(jīng)討論過了,EJB 3.0符合這種需求,而Spring作為一個(gè)通用的DI框架組件,不符合這個(gè)需求。

            當(dāng)然,EJB 3.0和Spring都在學(xué)習(xí)對方的最佳特性,它們都在某個(gè)程度上支持XML和注釋。例如,在EJB 3.0中XML配置文件是一個(gè)可選的重載機(jī)制,可以用于改變注釋的默認(rèn)行為。注釋也可以用于配置某㏒pring服務(wù)。

            認(rèn)識XML和注釋之間的區(qū)別的最好途徑是通過示例。在下一部分,我們會看到Spring和EJB 3.0是如何為應(yīng)用程序提供關(guān)鍵服務(wù)的。

                  宣告式服務(wù)(Declarative Services)

            Spring和EJB 3.0都把運(yùn)行時(shí)服務(wù)(例如事務(wù)、安全性、日志記錄、消息和定制服務(wù))捆綁到應(yīng)用程序上。由于這些服務(wù)都沒有直接地與應(yīng)用程序的業(yè)務(wù)邏輯相關(guān)聯(lián),因此它們不由應(yīng)用程序自身來管理。作為代替,這些服務(wù)是在運(yùn)行時(shí)由服務(wù)容器(例如Spring或EJB 3.0)透明地應(yīng)用在程序上的。開發(fā)者(或管理員)配置容器并告訴容器如何/什么時(shí)候應(yīng)用服務(wù)。

            EJB 3.0使用Java注釋配置宣告式服務(wù),而Spring使用XML配置文件。在大多數(shù)情況下,對于這類服務(wù),EJB 3.0注釋方法更加簡單,更加優(yōu)雅。下面是一個(gè)在EJB 3.0中給POJO方法應(yīng)用事務(wù)服務(wù)的例子。

          public class Foo {

          @TransactionAttribute(TransactionAttributeType.REQUIRED)
          public bar () {
          // 執(zhí)行某些操作 ...
          }
          }

            你也可以在一個(gè)代碼片斷中定義多個(gè)屬性,應(yīng)用多個(gè)服務(wù)。下面是一個(gè)在EJB 3.0中同時(shí)給POJO應(yīng)用了事務(wù)和安全性服務(wù)的例子:

          @SecurityDomain("other")
          public class Foo {

          @RolesAllowed({"managers"})
          @TransactionAttribute(TransactionAttributeType.REQUIRED)
          public bar () {
          // 執(zhí)行某些操作 ...
          }
          }

            使用XML指定代碼屬性和配置宣告式服務(wù)可能導(dǎo)致冗長的和不穩(wěn)定的配置文件。下面是一個(gè)在Spring應(yīng)用程序中利用XML元素給Foo.bar()方法應(yīng)用一個(gè)非常簡單的Hibernate事務(wù)服務(wù)的例子:

          <!-- 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>

            如果你給同一個(gè)POJO添加多個(gè)攔截器(interceptor,例如安全性攔截器),那么XML的復(fù)雜程度會呈幾何級數(shù)增長。Spring意識到了只使用XML配置文件的局限性,它現(xiàn)在支持在Java源代碼中使用Apache通用元數(shù)據(jù)指定事務(wù)屬性。在最新的Spring 1.2中,還支持JDK-1.5樣式的注釋。如果你要使用事務(wù)元數(shù)據(jù),就需要把上面的transactionAttributeSource bean改變成AttributesTransactionAttributeSource示例,并增加與元數(shù)據(jù)攔截器相關(guān)的額外配置。

          <bean id="autoproxy"
          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ù)簡化了transactionAttributeSource元素。但是它沒有解決XML配置文件的基本問題--冗長和脆弱,還是需要使用事務(wù)攔截器、transactionManager和transactionAttributeSource。

            依賴注入(Dependency Injection)

            中間件容器的關(guān)鍵優(yōu)勢在于它們允許開發(fā)者建立松散耦合的應(yīng)用程序。服務(wù)的客戶端只需要知道服務(wù)的接口。容器用具體的實(shí)現(xiàn)來初始化服務(wù)對象,并使客戶端能夠訪問它們。這就允許了容器在不同的服務(wù)實(shí)現(xiàn)之間進(jìn)行切換,而不需要改變接口或客戶端代碼。

            依賴注入(DI)模式是實(shí)現(xiàn)松散耦合的應(yīng)用程序的最好的方法之一。它比舊方法(例如通過JNDI的依賴查找或容器回調(diào))更易于使用、更優(yōu)雅。使用DI的時(shí)候,框架組件充當(dāng)建立服務(wù)對象的對象工廠,并根據(jù)運(yùn)行時(shí)配置,把這些服務(wù)對象注入應(yīng)用程序POJO中。從應(yīng)用程序開發(fā)者的角度來看,當(dāng)客戶端POJO需要使用某種服務(wù)對象的時(shí)候,它們會自動地獲取該對象。

            Spring和EJB 3.0都給DI模式提供了廣泛的支持,但是它們之間有一些深刻的差異。Spring支持普通的、但是復(fù)雜的、基于XML配置文件的DI API;EJB 3.0通過簡單的注釋支持大多數(shù)通用服務(wù)對象(例如EJB和上下文關(guān)系對象)和JNDI對象的注入操作。

            EJB 3.0 DI注釋非常簡潔,易于使用。@Resource標(biāo)簽注入大多數(shù)通用服務(wù)對象和JNDI對象。下面的例子演示了如何把JNDI中的服務(wù)器的默認(rèn)DataSource對象注入POJO的一個(gè)字段變量中。DefaultDS是JNDI用于表示DataSource的名稱。在第一次使用myDb變量之前,會把正確的值自動地賦給它。

          public class FooDao {

          @Resource (name="DefaultDS")
          DataSource myDb;

          // 使用 myDb 獲取數(shù)據(jù)庫的JDBC連接
          }

            作為對字段變量直接注入的補(bǔ)充,我們還可以使用EJB 3.0中的@Resource注釋,通過設(shè)置(setter)方法來注入對象。例如,下面的例子就注入了一個(gè)對話上下文關(guān)系(context)對象。應(yīng)用程序一直沒有顯式調(diào)用設(shè)置方法--該方法在被其它的任何方法調(diào)用之前,會先被容器調(diào)用。

          @Resource
          public void setSessionContext (SessionContext ctx) {
          sessionCtx = ctx;
          }

            對于更加復(fù)雜的服務(wù)對象,已經(jīng)定義了一些專用的注入注釋。例如,@EJB注釋用于注入EJB stub,@PersistenceContext注釋用于注入EntityManager對象(它為EJB 3.0實(shí)體bean處理數(shù)據(jù)庫訪問)。下面的例子演示了如何向一個(gè)有狀態(tài)的對話bean注入EntityManager對象。@PersistenceContext注釋的type屬性指明被注入的EntityManager擁有擴(kuò)展的事務(wù)上下文關(guān)系--它不會自動地與JTA事務(wù)管理器一起提交,因此它可以用于那些在一個(gè)對話中跨越多個(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);
          }
          }

            EJB 3.0規(guī)范定義了可以通過注釋注入的服務(wù)器資源。但是它不支持用戶自定義的應(yīng)用程序POJO的彼此相互注入。

            在Spring中,你首先需要為POJO的服務(wù)對象定義一個(gè)設(shè)置方法(或者帶參數(shù)的構(gòu)造函數(shù))。下面的例子顯示POJO需要一個(gè)指向Hibernate對話工廠的指針。

          public class FooDao {

          HibernateTemplate hibernateTemplate;

          public void setHibernateTemplate (HibernateTemplate ht) {
          hibernateTemplate = ht;
          }

          // 使用 Hibernate 模板訪問數(shù)據(jù)
          public Foo getFoo (Integer id) {
          return (Foo) hibernateTemplate.load (Foo.class, id);
          }
          }

            接下來,你可以指定容器如何在運(yùn)行時(shí)通過XML元素鏈獲取服務(wù)對象并把它捆綁到POJO上。下面的例子演示了把數(shù)據(jù)源捆綁到Hibernate對話工廠,把對話捆綁到Hibernate模板對象,最后把模板對象捆綁到應(yīng)用程序POJO的XML元素。這段Spring代碼如此復(fù)雜的部分原因在于我們必須手動地注入下層Hibernate管道對象,而EJB 3.0 EntityManager是由服務(wù)器自動地管理和配置的。但是這又讓我們回到了Spring沒有像EJB 3.0那樣與服務(wù)緊密集成的討論中了。

          <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(包括你在應(yīng)用程序中定義的)注入另一個(gè)POJO。如果你真的希望在EJB 3.0應(yīng)用程序中使用Spring的依賴注入能力,你可以通過JNDI把Spring bean工廠注入EJB中。在某些EJB 3.0應(yīng)用程序服務(wù)器中,廠商可能定義了額外的非標(biāo)準(zhǔn)的API,以注入任意的POJO。其中一個(gè)很好的例子是JBoss MicroContainer,它甚至比Spring更普通,因?yàn)樗幚砹嗣嫦蚍矫婢幊蹋ˋOP)的依賴性。

            結(jié)論

            盡管Spring和EJB 3.0的目標(biāo)都是為松散耦合的POJO提供企業(yè)級服務(wù),但是它們是使用截然不同的方法來達(dá)到這個(gè)目標(biāo)的。在這兩個(gè)框架組件中都大量地使用了依賴注入(DI)。

            使用EJB 3.0的時(shí)候,基于標(biāo)準(zhǔn)的方法、注釋的大量使用、以及與應(yīng)用程序服務(wù)器的緊密集成形成了強(qiáng)大的廠商無關(guān)性和開發(fā)者的高效率。使用Spring的時(shí)候,一致地使用依賴注入和集中的XML配置文件,允許開發(fā)者構(gòu)造更加靈活的應(yīng)用程序,并在同一時(shí)刻使用多個(gè)應(yīng)用服務(wù)

          posted on 2007-05-10 09:00 常言笑 閱讀(433) 評論(0)  編輯  收藏 所屬分類: JAVA/J2EE

          My Links

          Blog Stats

          常用鏈接

          留言簿(5)

          隨筆分類

          隨筆檔案

          搜索

          積分與排名

          最新評論

          閱讀排行榜

          評論排行榜

          主站蜘蛛池模板: 顺义区| 沈阳市| 阿拉善左旗| 报价| 同江市| 黔西| 兰坪| 和林格尔县| 阿拉善左旗| 葵青区| 三台县| 会同县| 舒兰市| 建德市| 江西省| 灌云县| 林西县| 航空| 探索| 大埔区| 广汉市| 龙口市| 沙河市| 西藏| 林周县| 乐陵市| 怀来县| 琼海市| 文成县| 邻水| 巴彦县| 晋州市| 菏泽市| 科尔| 绍兴市| 方城县| 安多县| 安康市| 乌兰县| 舟曲县| 万荣县|