<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    大鳥的學習樂園
    路漫漫其修遠兮,吾將上下而求索
    posts - 26,comments - 27,trackbacks - 0
    POJO應用框架:Spring Vs. EJB 3.0
    2009年02月27日 星期五 21:27
    愛因斯坦曾經說:“任何事情都應該越簡單越好,而不是比較簡單。”實際上,科學真理的目的就是在假設的前提下去簡化一個理論,這樣,人們可以去關注真正重要的問題。在企業軟件開發中,道理是一樣的。
      簡化企業軟件開發的一個關鍵是,提供一個這樣的應用框架:它可以使開發人員不用關注于很多復雜的問題,比如事務處理、安全和持久化等。一個設計良好的框架將提升代碼的可復用性,提高開發者的效率,并得到更高質量的軟件。然而,目前J2EE 1.4下的EJB 2.1 框架被廣泛認為是設計較差而且過度復雜的。不滿足于EJB2.1框架,JAVA開發者使用了很多其他的中間件服務產品。最值得關注的是,以下兩個框架吸引了大量開發者的興趣和積極反饋。這兩個框架很可能成為未來企業JAVA應用開發框架的選擇。
      Spring框架是一個廣受歡迎的但是非標準的開源框架。它主要由Interface21公司開發和控制。Spring框架的體系結構是基于注射依賴(DI)模式。Spring框架使用了大量的XML配置文件,它可以獨立應用,或者在現有的應用服務器上工作。
      EJB 3.0框架是JCP定義的并且被所有主流J2EE提供商支持的標準框架。EJB 3.0規范的預發布版本目前已經有開源的和商業的實現,如JBOSS和ORACLE。EJB 3.0大量使用了JAVA注解(Java annotations,是JDK1.5提供的新功能。譯者注)
      這兩個框架有著一個共同的核心設計理念:它們的目標是為松耦合的POJO類提供中間件服務。框架通過在運行時截取執行環境,或將服務對象注射給POJO類的方式,將應用服務和POJO類“連接”起來。POJO類本身并不關注如何“連接”,而且也很少依賴于框架。這樣,開發者可以將注意力集中在業務邏輯上,可以對他們的POJO類進行與框架無關的單元測試。并且,由于POJO類不需要繼承框架的類或實現框架提供的接口,開發者可以在更加靈活性的基礎上構建繼承體系,和搭建應用。
      盡管有著共同的理念,但這兩個框架采取了不同的方式來提供POJO服務。由于已經出版了大量的比較Spring與EJB2.1或者EJB3.0與EJB2.1的書籍和文章,而沒有關于比較Spring和EJB3.0的認真研究,因此,本文將考察它們之間幾個關鍵的不同,討論他們優缺點。本文談到的主題同樣適用于其他不太有名的但同樣提供“松耦合POJO” 設計的企業中間件框架。我希望,這篇文章可以幫助你選者最合適的你需求的框架。
    提供商無關性
      開發者選擇JAVA平臺的一個最重要的原因就是它的提供廠商無關性。EJB 3.0是一個被設計為對提供商沒有依賴性的開放的標準。EJB 3.0規范由企業JAVA社區的主流開源組織和廠商共同編寫和支持的。EJB 3.0框架使開發者的應用程序實現可以獨立于應用服務器。比如,JBoss的EJB 3.0的實現是基于Hibernate的,Oracle的EJB 3.0實現是基于TopLink的,但是,在JBoss或者Oracle上跑應用程序,開發者既不需要去學習Hibernate,也不需要學習TopLink提供的獨特API。廠商無關性使EJB 3.0框架區別于當前其他任何的POJO中間件框架。
      然而,就象很多EJB 3.0的批評者很快指出的一樣,目前EJB 3.0規范正在編寫還未完全完成最終發布版。很有可能,還需要1至2年,EJB 3.0才會被主流J2EE廠商完全接受。但是,就算你的應用服務器本身不支持EJB 3.0,你也可以通過下載和安裝一個“可嵌入的” EJB 3.0產品,來使你的應用服務器支持EJB 3.0應用。比如,JBoss“可嵌入的” EJB 3.0產品是開源的,它可以運行在任何兼容J2SE-5.0環境下(如你的應用服務器),目前處于Beta版測試中。其他廠商同樣可以快速發布他們自己的可嵌入EJB 3.0產品,特別是規范中“數據持久化”部分。
      另一方面,Spring一直是一個非標準的技術,而且在可以預計的未來仍將如此。盡管你在任何應用服務器都上可以使用Spring框架,但基于Spring的應用仍然被限制于Spring本身和在你的應用中使用到的Spring提供的各種特別服務。
      由于Spring框架是一個開源項目,因此,它使用的配置文件XML格式和開發接口都是私有的。當然,這種限制不僅體現在Spring框架中,其他任何非標準產品都會有這種限制。但是,你的Spring應用的長期生存能力將依賴于Spring項目本身(或者說Interface 21公司,因為它雇傭了大多數的Spring核心開發人員)。并且,如果你使用了Spring提供的特殊服務,如Spring事務管理器或者Spring MVC,你同樣被限制于Spring提供的API。
      并且,Spring應用是知道后端服務提供者的(即應用程序是知道服務提供者的,這樣應用程序將會在一定程度上依賴于服務提供方:譯者注)。例如,對于數據持久化服務,Spring框架提供了不同的DAO和模板Helper類,用于JDBC、Hibernate,、iBatis和JDO。這樣,假如你需要改變一個Spring應用的持久化服務提供者(如,從JDBC換到Hibernate),你將需要重構你的系統應用代碼,來使用新的Helper類。
    服務整合
      Spring框架是建立在應用服務器和服務庫之上,它的服務整合代碼(如數據訪問模板和Helper類)是基于框架的,并暴露給應用開發者。相反,EJB 3.0框架是緊密整合到應用服務器中的,它的服務整合代碼是封裝在一個標準的接口下的。
      因此,EJB 3.0廠商可以輕松的優化整體性能和開發者體驗。如,在JBoss的EJB 3.0實現中,當你通過實體管理器持久化一個實體BEAN POJO時,Hibernate session事務將在JTA事務提交時自動提交。通過使用簡單的@PersistenceContext注解(例子參看后面文章),你可以甚至可以將實體管理器和其下的Hibernate事務綁定到一個有狀態的session bean上。應用程序事務可以在一個session中跨越多個線程,在事務性的WEB應用中這是非常有用的,如多頁面的購物車。
      基于EJB 3.0 框架、Hibernate、和JBoss 內部Tomcat的緊密整合,上面提到的簡單的整合的編程接口是可能的。Oracle的EJB 3.0框架和它內部的Toplink持久服務可以達到同樣層次的整合。
      EJB 3.0中整合服務的另一個好例子是集群支持。假如你部署一個EJB 3.0應用到一個集群服務器,所有的故障切換、負載均衡、分布式緩存、和狀態復制服務對于應用程序來說,都是自動完成的。集群服務被隱藏在EJB 3.0編程接口之下,對于EJB 3.0開發者來說,這些服務都是完全透明的。
      在Spring中,優化框架和服務之間交互更加困難一些。例如,想要用Spring的聲明式事務服務來管理Hibernate事務,必須在XML配置文件中明確的配置Spring的事務管理器(TransactionManager)和Hibernate SessionFactory對象。Spring應用開發者必須自己管理跨越多個HTTP請求的事務。并且,沒有簡單的方法可以在Spring應用中實現集群服務
    服務聚合的靈活性
      由于Spring中的服務整合代碼是作為編程接口暴露給應用開發者的,因此開發人員可以根據需要來聚合多個服務。這個特性使你可以集成一個你自己的“輕量”級應用服務器。Spring的一個通常的用法是將Tomcat和Hibernate連接起來來支持簡單的數據庫驅動的WEB應用程序。在這種情況下,Spring本身提供了事務管理服務,Hibernate提供了持久化服務,這種設置本身就創建了一個小型的應用服務器。
      通常,EJB 3.0應用服務器不提供給開發者這種按照你的需要來選擇服務的靈活性。大多數情況,你會得到一系列已經預先打包好的特性,其中有些你可能是不需要的。然而,如果應用服務器提供了模塊內部的獨特設計,就象JBOSS一樣,你可以不去關心這些不必要的特性。在任何情況下,去定制一個全功能的應用服務器并不是一個瑣碎而沒有意義的工作。
      當然,如果一個應用不是一個單一的結點,你將需要連接多個應用服務器提供的服務(如資源池、消息隊列和集群)。這種情況下,從總的資源消耗上看,Spring框架就和任何EJB 3.0方案一樣是“重量級”的。
      為了進行容器外的單元測試,Spring的靈活的服務聚合也可以來連接假對象,來替代真的服務對象。在EJB 3.0應用中,大多數的組件都是簡單POJO,他們可以容易進行容器外的單元測試。但是,如果要測試與容器服務相關的服務對象(如持久化實體管理器),更好的方式是進行容器內的測試,因為這樣比使用假對象來替代的方式更加容易,更加健壯,而且更加準確。
    XML vs. 注解
      從應用開發者的角度來看,Spring的編程接口主要基于XML配置文件,而EJB 3.0則大量的使用了JAVA注解。XML文件可以表達復雜的關系,但是它們更加冗長而且不健壯。注解的方式很簡單明了,但是很難去表達復雜的或者繼承性的結構。
      Spring和EJB 3.0分別選擇了XML和注解方式,這取決于框架的體系結構:由于注釋只能描述相當少的配置信息,只有一個預先整合好的框架(如大多數重要事情已經在框架中實現了)才能大量的使用注釋作為它的配置選項。象我們討論的一樣,EJB 3.0滿足了這些要求,而Spring作為一個一般的注射依賴框架,它沒有做到這一點。
      當然,由于EJB 3.0和Spring相互學習了很多特性,所以,它們都在某種層次上支持XML和注釋。例如,EJB 3.0中可以應用XML配置文件來作為一個選擇性的機制,用來改變注釋的默認行為。注釋也可以用來配置一些Spring服務。
      研究XML和注釋直接區別的最好的方式就是通過例子。在下面的幾節中,我們將一起看一下EJB 3.0和Spring是如何為應用程序提供關鍵服務的。
    聲明式服務
      EJB 3.0和Spring都將運行時服務(如事務管理、安全、日志、消息、和信息服務)連接給應用程序。由于這些服務同應用程序的業務邏輯并不是直接相關的,因此,它們不被應用程序本身來管理。相反,這些服務被服務容器(如EJB 3.0和Spring)以不可見的方式在運行時提供給應用程序。開發人員(或系統管理員)通過配置來告訴容器什么時候,以怎樣的方式來應用這些服務。
      EJB 3.0通過JAVA注解的方式來配置聲明式服務,Spring則通過XML配置文件來完成。大多數情況下,EJB 3.0 的注解方式是應用這種服務的更加簡單和優美的方式。下面是一個在EJB 3.0中對一個POJO的方法使用事務管理服務的例子。
      public class Foo {
          @TransactionAttribute(TransactionAttributeType.REQUIRED)
          public bar () {
            // do something ...
          }   
      }
      你可以對一段代碼聲明多個屬性,并應用多個服務。下面是一個對EJB 3.0中POJO類同時使用事務管理服務和安全服務的例子。
      @SecurityDomain("other")
      public class Foo {
          @RolesAllowed({"managers"})
          @TransactionAttribute(TransactionAttributeType.REQUIRED)
          public bar () {
            // do something ...
          }  
      }
      使用XML指定代碼屬性和配置聲明服務將導致冗長的和不桅頂的配置文件。下面是Spring應用中一個XML元素的例子,它用來在Foo.bar()方法上應用一個非常簡單的Hibernate事務。
    <!-- 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 -->
            <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文件的復雜程度將隨著你對同一個POJO類增加的攔截器的數量程幾何增長。意識到了僅使用XML配置文件的限制性,Spring支持在JAVA源代碼中使用Apache Commons metadata來指定事物屬性。在最新的Spring 1.2中,JDK-1.5風格的注釋也被支持。為了使用事務元數據,你需要為上面例子中的AttributesTransactionAttributeSource 改變一個transactionAttributeSource bean,并且增加一個附加的對元數據攔截器的設置。
    <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"/>
      
      當你有許多事務方法時,Spring元數據簡化了transactionAttributeSource元素。但是它沒有解決XML配置文件的根本問題:仍然需要冗長的、易錯的事務攔截器,事務管理器,和事務屬性。
    注射依賴
      中間件容器的一個主要優點是它們使得程序開發人員可以去構建松耦合的應用程序。服務使用者僅僅需要知道服務接口就可以使用服務。容器把具體的服務實現實例化,然后將它們提供給服務使用者。這樣,容器可以在可替換的服務實現之間進行切換,而不改變服務接口和服務使用者代碼。
      注射依賴模式是實現松耦合應用程序的一個最好的方式。比起以前的方式,如通過JNDI進行查找或回調容器,注射依賴模式更容易使用,而且更加優美。使用注射依賴模式,框架扮演了構建服務的對象工廠角色,然后根據運行時的配置,把這些服務對象注射到應用程序的POJO類中。從程序開發人員的角度看,作為客戶端使用者的POJO在需要使用服務對象前就自動的得到了它們。
      Spring 和 EJB 3.0都提供了大量的DI模式支持。但是,它們之間也有著根本的不同。Spring支持了通常意義上的但是復雜的基于XML配置文件的注射依賴API;EJB 3.0支持的注射大多數通用服務對象(如,EJB和容器對象)和JNDI對象,它通過簡單的JAVA注解來完成。
      EJB 3.0的注射注解相當的簡潔易用。@Resource標簽注射大多數的通過服務對象和JNDI對象。下面的例子顯示了如何將JNDI提供的服務器缺剩數據源對象注射給一個POJO的一個字段。DefaultDS是這個數據源的JNDI名字。myDb 變量在第一次被使用前就自動被賦予了正確的值。
      public class FooDao {
          @Resource (name="DefaultDS")
          DataSource myDb;
          // Use myDb to get JDBC connection to the database
      }
      在EJB 3.0中,注釋@Resource不僅可以直接注射給屬性變量,它也可以通過setter方法來完成注射。下面的例子將一個session上下文對象通過setter方法注射給使用者。應用程序不用顯示的調用setter方法,在任何其他方法被調用前容器將調用setter方法完成注射。
      @Resource
      public void setSessionContext (SessionContext ctx) {
          sessionCtx = ctx;
      }
      對于更復雜的服務對象,還有一些特殊的注射注解。例如,@EJB 注解被用來注射EJB stubs,@PersistenceContext注解被用來注射實體管理器對象,這些對象負責處理EJB 3.0實體Bean的數據訪問操作。 下面的例子給出如何將一個實體管理器注射到一個有狀態Session Bean中。@PersistenceContext注解的類型屬性描述了被注射的的實體管理器有一個擴展的事務容器:它不會隨著JTA事務管理器自動提交事務,因此它可以應用在當session中有多次操作的應用事務管理時。
      @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 規范定義了可以通過注解來被注射使用的服務器資源。但是,它不支持用戶自定義的POJO類之間的相互注射。
      在Spring中,為了將服務對象注射到你的POJO類中,你首先需要定義一個setter方法(或有參數的構造函數) 。下面的例子演示了 POJO 類中一個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元素的連接關系把它提供給POJO。下面的例子顯示了連接一個數據源到一個Hibernate session 工廠、session 工廠到Hibernate模板對象、模板對象最后到應用程序POJO類,整個過程的XML配置。
      Spring 代碼復雜性的部分原因是,我們需要手工的去注射Hibernate相關類,然而,EJB 3.0 實體管理器被服務器自動管理和配置。但是,這使我們返回到了這樣的討論:Spring 不象EJB 3.0 一樣,它不同服務緊密整合在一起。
    <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的注射依賴比較復雜,但是它非常強大。你可以注射任何POJO到另外的POJO中,包括程序中自定義的。
      如果你確實想在EJB 3.0應用中使用Spring的注射依賴功能,你可以將一個Spring Bean工廠類通過JNDI注射到一個EJB中。在某些EJB 3.0 應用服務器中,廠商可能會定義一些非標準的API用來注射任意的POJO類。一個很好的例子是JBoss MicroContainer,它處理了AOP依賴性,因此它是甚至比Spring 更加通用。
      
    結論
      盡管Spring 和EJB 3.0的目標都是提供企業服務,使得POJO可以松耦合,但是它們實現的方式非常不同。在兩個框架中注射依賴模式都有大量的應用。
      通過EJB 3.0的標準方式、大量應用的注解、還有同應用服務器緊密整合性,這些提供了更高的廠商無關性和開發人員工作效率。Spring的以XML為中心的配置文件和注射依賴的連貫使用,允許開發人員去構造更加靈活的應用系統,并且可以同時與多個應用服務提供者同時工作。

    posted on 2009-12-23 10:02 大鳥 閱讀(148) 評論(0)  編輯  收藏 所屬分類: JAVA EE6
    主站蜘蛛池模板: 亚洲高清视频一视频二视频三| 国产桃色在线成免费视频 | 中文字幕在线观看亚洲视频| 久久精品私人影院免费看| 亚洲老妈激情一区二区三区| 国产区在线免费观看| 国产亚洲精品精品国产亚洲综合| xxxxxx日本处大片免费看| 亚洲精品一级无码中文字幕| 一级日本高清视频免费观看| 亚洲午夜国产精品无码| 免费看黄的成人APP| 91情国产l精品国产亚洲区| 97在线视频免费公开观看| 亚洲春色在线观看| 亚洲一区二区三区免费在线观看 | 亚洲中文字幕人成乱码| 69成人免费视频| 亚洲欧洲专线一区| 又粗又大又猛又爽免费视频 | 国产午夜亚洲精品午夜鲁丝片 | 猫咪社区免费资源在线观看| 在线看亚洲十八禁网站| 亚洲人成无码网WWW| 污污网站免费观看| 99999久久久久久亚洲| 国产免费啪嗒啪嗒视频看看| 国产又黄又爽胸又大免费视频| 亚洲av日韩av天堂影片精品| 无人在线观看免费高清视频 | 国产AV无码专区亚洲AV蜜芽| 2048亚洲精品国产| 18禁美女裸体免费网站 | 亚洲国产精品无码av| 亚洲精品视频免费看| 亚洲AV性色在线观看| 久久久久亚洲精品无码网址 | 免费国产va在线观看| 亚洲自偷自拍另类12p| 永久久久免费浮力影院| a级毛片在线免费观看|