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

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

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

    Sung in Blog

               一些技術文章 & 一些生活雜碎
    Introducing to Spring Framework

    作者:Rod Johnson
    譯者:yanger,taowen
    校對:taowen

    關于Spring Framework,今年夏天你可能已經聽見很多的議論。在本文中,我將試圖解釋Spring能完成什么,和我怎么會認為它能幫助你開發J2EE應用程序。

    又來一個framework?

    你可能正在想“不過是另外一個的framework”。當已經有許多開放源代碼(和專有) J2EE framework時,為什么你還要耐下心子讀這篇文章或去下載Spring Framework?

    我相信Spring是獨特的,有幾個原因:


      它關注的領域是其他許多流行的Framework未曾關注的。Spring要提供的是一種管理你的業務對象的方法。

      Spring既是全面的又是模塊化的。Spring有分層的體系結構,這意味著你能選擇僅僅使用它任何一個獨立的部分,而它的架構又是內部一致。因此你能從你的學習中,得到最大的價值。例如,你可能選擇僅僅使用Spring來簡單化JDBC的使用,或用來管理所有的業務對象。

      它的設計從一開始就是要幫助你編寫易于測試的代碼。Spring是使用測試驅動開發的工程的理想框架。

    Spring不會給你的工程添加對其他的框架依賴。Spring也許稱得上是個一站式解決方案,提供了一個典型應用所需要的大部分基礎架構。它還涉及到了其他framework沒有考慮到的內容。

    盡管它僅僅是一個從2003年2月才開始的開源項目,但Spring有深厚的歷史根基。這個開源工程是起源自我在2002年晚些時候出版的《Expert One-on-One J2EE設計與開發》書中的基礎性代碼。這本書展示了Spring背后的基礎性架構思想。然而,對這個基礎架構的概念可以追溯到2000年的早些時候,并且反映了我為一系列商業工程開發基礎結構的成功經驗。

    2003年1月,Spring已經落戶于SourceForge上了。現在有10個開發人員,其中6個是高度投入的積極分子。

    Spring架構上的好處

    在我們進入細節之前,讓我們來看看Spring能夠給工程帶來的種種好處:


      Spring能有效地組織你的中間層對象,不管你是否選擇使用了EJB。如果你僅僅使用了Struts或其他為J2EE的 API特制的framework,Spring致力于解決剩下的問題。

      Spring能消除在許多工程中常見的對Singleton的過多使用。根據我的經驗,這是一個很大的問題,它降低了系統的可測試性和面向對象的程度。

      通過一種在不同應用程序和項目間一致的方法來處理配置文件,Spring能消除各種各樣自定義格式的屬性文件的需要。曾經對某個類要尋找的是哪個魔法般的屬性項或系統屬性感到不解,為此不得不去讀Javadoc甚至源編碼?有了Spring,你僅僅需要看看類的JavaBean屬性。Inversion of Control的使用(在下面討論)幫助完成了這種簡化。

      通過把對接口編程而不是對類編程的代價幾乎減少到沒有,Spring能夠促進養成好的編程習慣。

      Spring被設計為讓使用它創建的應用盡可能少的依賴于他的APIs。在Spring應用中的大多數業務對象沒有依賴于Spring。

      使用Spring構建的應用程序易于單元測試。

      Spring能使EJB的使用成為一個實現選擇,而不是應用架構的必然選擇。你能選擇用POJOs或local EJBs來實現業務接口,卻不會影響調用代碼。

      Spring幫助你解決許多問題而無需使用EJB。Spring能提供一種EJB的替換物,它們適用于許多web應用。例如,Spring能使用AOP提供聲明性事務管理而不通過EJB容器,如果你僅僅需要與單個數據庫打交道,甚至不需要一個JTA實現。

      Spring為數據存取提供了一個一致的框架,不論是使用的是JDBC還是O/R mapping產品(如Hibernate)。

    Spring確實使你能通過最簡單可行的解決辦法來解決你的問題。而這是有有很大價值的。

    Spring做了些什么?

    Spring提供許多功能,在此我將依次快速地展示其各個主要方面。

    任務描述

    首先,讓我們明確Spring范圍。盡管Spring覆蓋了許多方面,但我們對它應該涉什么,什么不應該涉及有清楚的認識。

    Spring的主要目的是使J2EE易用和促進好編程習慣。

    Spring不重新輪子。因此,你發現在Spring中沒有logging,沒有連接池,沒有分布式事務調度。所有這些東西均有開源項目提供(例如我們用于處理所有日志輸出的Commons Logging以及Commons DBCP),或由你的應用程序服務器提供了。出于同樣的的原因,我們沒有提供O/R mapping層。對于這個問題已經有了像Hibernate和JDO這樣的優秀解決方案。

    Spring的目標就是讓已有的技術更加易用。例如,盡管我們沒有底層事務協調處理,但我們提供了一個抽象層覆蓋了JTA或任何其他的事務策略。

    Spring沒有直接和其他的開源項目競爭,除非我們感到我們能提供新的一些東西。例如,象許多開發人員一樣,我們從來沒有對Struts感到高興過,并且覺得到在MVC web framework中還有改進的余地。在某些領域,例如輕量級的IoC容器和AOP框架,Spring確實有直接的競爭,但是在這些領域還沒有已經較為流行的解決方案。(Spring在這些領域是開路先鋒。)

    Spring也得益于內在的一致性。所有的開發者都在唱同樣的的贊歌,基礎想法依然與Expert One-on-One J2EE設計與開發中提出的差不多。 并且我們已經能夠在多個領域中使用一些中心的概念,例如Inversion of Control。

    Spring在應用服務器之間是可移植的。當然保證可移植性總是一種挑戰,但是我們避免使用任何平臺特有或非標準的東西,并且支持在WebLogic,Tomcat,Resin,JBoss,WebSphere和其他的應用服務器上的用戶。

    Inversion of Control 容器

    Spring設計的核心是 org.springframework.beans 包, 它是為與JavaBeans一起工作而設計的。 這個包一般不直接被用戶使用,而是作為許多其他功能的基礎。

    下一個層面高一些的抽象是"Bean Factory"。一個Spring bean factory 是一個通用的Factory,它使對象能夠按名稱獲取,并且能管理對象之間的關系。

    Bean factories 支持兩種模式的對象:


      Singleton:在此模式中,有一個具有特定名稱的共享對象實例,它在查找時被獲取。這是默認的,而且是最為經常使用的。它對于無狀態對象是一種理想的模式。

      Prototype:在此模式中,每次獲取將創建一個獨立的對象。例如,這可以被用于讓用戶擁有他們自己的對象。


    由于 org.springframwork.beans.factory.BeanFactory是一個簡單的接口,它能被大量底層存儲方法實現。你能夠方便地實現你自己的BeanFactory,盡管很少用戶需要這么做。最為常用的BeanFactory定義是:


      XmlBeanFactory: 可解析簡單直觀的定義類和命名對象屬性的XML結構。 我們提供了一個DTD來使編寫更容易。

      ListableBeanFactoryImpl:提供了解析存放在屬性文件中的bean定義的能力,并且可通過編程創建BeanFactories。

    每個bean定義可能是一個POJO(通過類名和JavaBean初始屬性定義),或是一個FactoryBean。FactoryBean接口添加了一個間接層。通常,這用于創建使用AOP或其他方法的代理對象:例如,添加聲明性事務管理的代理。(這在概念上和EJB的interception相似,但實現得更簡單。)

    BeanFactories能在一個層次結構中選擇性地參與,繼承ancestor(祖先)的定義。這使得在整個應用中公共配置的共享成為可能,雖然個別資源,如controller servlets,還擁有他們自己的獨立的對象集合。

    這種使用JavaBeans的動機在《Expert One-on-One J2EE Design and Development》的第四章中有描述,在TheServerSide網站上的有免費的PDF版本(http://www.theserverside.com/resources/article.jsp?l=RodJohnsonInterview)。

    通過BeanFactory概念,Spring成為一個Inversion of Control的容器。(我不怎么喜歡container這個詞,因為它使人聯想到重量級容器,如EJB容器。Spring的BeanFactory是一個可通過一行代碼創建的容器,并且不需要特殊的部署步驟。)

    Inversion of Control背后的概念經常表述為Hollywood原則的:“Don’t call me, I’ll call you。” IoC將控制創建的職責搬進了框架中,并把它從應用代碼脫離開來。涉及到配置的地方,意思是說在傳統的容器體系結構中,如EJB,一個組件可以調用容器并問“我需要它給我做工作的對象X在哪里?”;使用IoC容器則只需指出組件需要X對象,在運行時容器會提供給它。容器是通過查看方法的參數表(例如JavaBean的屬性)做到的,也可能根據配置數據如XML。

    IoC有幾個重要的好處,例如:


      因為組件不需要在運行時間尋找合作者,所以他們可以更簡單的編寫和維護。在Spring版的IoC里,組件通過暴露JavaBean的setter方法表達他們依賴的其他組件。這相當于EJB通過JNDI來查找,EJB查找需要開發人員編寫代碼。

      同樣原因,應用代碼更容易測試。JavaBean屬性是簡單的,屬于Java核心的,并且是容易測試的:僅編寫一個自包含的Junit測試方法用來創建對象和設置相關屬性即可。

      一個好的IoC實現保留了強類型。如果你需要使用一個通用的factory來尋找合作者,你必須通過類型轉換將返回結果轉變為想要的類型。這不是一個大不了的問題,但是不雅觀。使用IoC,你在你的代碼中表達了強類型依賴,框架將負責類型轉換。這意味著在框架配置應用時,類型不匹配將導致錯誤;在你的代碼中,你無需擔心類型轉換異常。

      大部分業務對象不依賴于IoC容器的APIs。這使得很容易使用遺留下來的代碼,且很容易的使用對象無論在容器內或不在容器內。例如,Spring用戶經常配置Jakarta Commons DBCP數據源為一個Spring bean:不需要些任何定制代碼去做這件事。我們說一個IoC容器不是侵入性的:使用它并不會使你的代碼依賴于它的APIs。任何JavaBean在Spring bean factory中都能成為一個組件。

    最后應該強調的是,IoC 不同于傳統的容器的體系結構,如EJB,應用代碼最小程度地依靠于容器。這意味著你的業務對象可以潛在的被運行在不同的IoC 框架上——或者在任何框架之外——不需要任何代碼的改動。

    以我和其他Spring用戶的經驗來說,再怎么強調IoC給應用程序代碼帶來的好處也不為過。

    IoC不是一個新概念,但是它在J2EE團體里面剛剛到達黃金時間。 有一些可供選擇的IoC 容器: 例如 Apache Avalon, PicoContainer 和 HiveMind。Avalon 從沒怎么流行,盡管它很強大而且有很長的歷史。Avalon相當的重和復雜,并且看起來比新的IoC解決方案更具侵入性。 PicoContainer是一個輕量級而且更強調通過構造函數表達依賴性而不是JavaBean 屬性。 與Spring不同,它的設計允許每個類型一個對象的定義(可能是因為它拒絕任何Java代碼外的元數據導致的局限性)。在Spring, PicoContainer 和其他 IoC frameworks之間做比較,可參看文章Spring網站上的"The Spring Framework - A Lightweight Container"位于http://www.springframework.org/docs/lightweight_container.html。這個頁面里面包含了PicoContainer站點的鏈接 。

    Spring BeanFactories 是非常輕量級的。用戶已經成功地將他們應用在applets和單獨的Swing應用中。(它們也很好地工作在EJB容器中。) 沒有特殊的部署步驟和察覺得到的啟動時間。這個能力表明一個容器在應用的任何層面幾乎立即可以發揮非常大的價值。

    Spring BeanFactory 概念貫穿于Spring始終, 而且是Spring如此內在一致的關鍵原因。在IoC容器中,Spring也是唯一的,它使用IoC作為基礎概念貫穿于整個功能豐富的框架。

    對應用開發人員,最重要的是,一個或多個BeanFactory提供了一個定義明確的業務對象層。這類似于local session bean層,但比它更簡單。與EJBs不同,在這個層中的對象可能是相關的,并且他們的關系被擁有它們的factory管理。有一個定義明確的業務對象層對于成功的體系結構是非常重要的。

    Spring ApplicationContext 是BeanFactory的子接口,為下列東西提供支持:


      信息查找,支持著國際化

      事件機制,允許發布應用對象以及可選的注冊以接收到事件

      可移植的文件和資源訪問

    XmlBeanFactory 例子

    Spring用戶通常在XML的“bean定義”文件中配置他們的應用。Spring的XML bean定義文檔的根是<beans> 元素。該元素包含一個或多個 <bean>定義。我們一般給每個bean定義的指定類和屬性。我們還必須指定ID作為標識,這將成為在代碼中使用該bean的名字。

    讓我們來看一個簡單的例子,它配置了三個應用程序對象,之間的關系在J2EE應用中常常能夠看到:


      J2EE DataSource

      使用DataSource的DAO

      在處理過程中使用DAO的業務對象

    在下面的例子中,我們使用一個來自Jakarta Commons DBCP項目的BasicDataSource。這個class(和其他許多已有的class一樣)可以簡單地被應用在Spring bean factory中,只要它提供了JavaBean格式的配置。需要在shutdown時被調用的Close方法可通過Spring的"destroy-method"屬性被注冊,以避免BasicDataSource需要實現任何Spring 的接口。

    代碼:
    <beans>

      <bean id="myDataSource"
    class="org.apache.commons.dbcp.BasicDataSource"
    destroy-method="close">
        <property name="driverClassName"><value>com.mysql.jdbc.Driver</value></property>
        <property name="url"><value>jdbc:mysql://localhost:3306/mydb</value></property>
        <property name="username"><value>root</value></property>
      </bean>

    BasicDataSource中我們感興趣的所有屬性都是String類型的,因此我們用<value>元素來指定他們的值。如果必要的話,Spring使用標準的 JavaBean屬性編輯器機制來把String轉換為其他的類型。

    現在,我們定義DAO,它有一個對DataSource的bean引用。Bean間關系通過<ref>元素來指定:

    代碼:
    <bean id="exampleDataAccessObject"
          class="example.ExampleDataAccessObject">
        <property name="dataSource"><ref bean="myDataSource"/></property>
      </bean>

    The business object has a reference to the DAO, and an int property (exampleParam):
    <bean id="exampleBusinessObject"
          class="example.ExampleBusinessObject">
        <property name="dataAccessObject"><ref bean="exampleDataAccessObject"/></property>
        <property name="exampleParam"><value>10</value></property>
      </bean>

    </beans>

    對象間的關系一般在配置中明確地設置,象這個例子一樣。我們認為這樣做是件好事情。然而Spring還提供了我們稱做"autowire"的支持, 一個la PicoContainer,其中它指出了bean間的依賴關系。這樣做的局限性——PicoContainer也是如此——是如果有一個特殊類型的多個Bean,要確定那個類型所依賴的是哪個實例是不可能。好的方面是,不滿足的依賴可以在factory初始化后被捕獲到。(Spring 也為顯式的配置提供了一種可選的依賴檢查,它可以完成這個目的)

    在上面的例子中,如果我們不想顯式的編寫他們的關系,可使用如下的autowire特性:

    代碼:
    <bean id="exampleBusinessObject"
       class="example.ExampleBusinessObject"
       autowire="byType">

        <property name="exampleParam"><value>10</value></property>
     </bean>


    使用這個特性,Spring會找出exampleBusinessObject的dataSource屬性應該被設置為在當前BeanFactory中找到的DataSource實現。在當前的BeanFactory中,如果所需要類型的bean不存在或多于一個,將產生一個錯誤。我們依然要設置exampleParam屬性,因為它不是一個引用。

    Autowire支持和依賴檢查剛剛加入CVS并將在Spring 1.0 M2(到10/20,2003)中提供。本文中所討論的所有其他特性都包含在當前1.0 M1版本中。

    把管理從Java代碼中移出來比硬編碼有很大的好處,因為這樣可以只改變XML文件而無需改變一行Java代碼。例如,我們可以簡單地改變myDataSource的bean定義引用不同的bean class以使用別的連接池,或者一個用于測試的數據源。 XML節變成另一種,我們可以用Spring的JNDI location FactoryBean從應用服務器獲取一個數據源。

    現在讓我們來看看例子中業務對象的java 代碼。注意下面列出的代碼中沒有對Spring的依賴。不像EJB容器,Spring BeanFactory不具有侵入性:在應用對象里面你通常不需要對Spring的存在硬編碼。

    代碼:
    public class ExampleBusinessObject implements MyBusinessObject {

       private ExampleDataAccessObject dao;
       private int exampleParam;

       public void setDataAccessObject(ExampleDataAccessObject dao) {
          this.dao = dao;
       }

       public void setExampleParam(int exampleParam) {
          this.exampleParam = exampleParam;
       }

       public void myBusinessMethod() {
          // do stuff using dao
       }
    }

    注意那些property setter,它們對應于bean定義文檔中的XML引用。這些將在對象被使用之前由Spring調用。

    這些應用程序的bean不需要依賴于Spring:他們不需要實現任何Spring的接口或者繼承Spring的類。他們只需要遵守JavaBeans的命名習慣。在Spring 應用環境之外重用它們是非常簡單的,例如,在一個測試環境中。只需要用它們的缺省構造函數實例化它們,并且通過調用setDataSource()和setExampleParam()手工設置它的屬性。如果你想以一行代碼支持程序化的創建,只要你有一個無參數的構造器,你就可以自由定義其他需要多個屬性的構造函數。

    注意在業務接口中沒有聲明將會一起使用的JavaBean屬性。 他們是一個實現細節。我們可以“插入”帶有不同bean屬性的不同的實現類而不影響連接著的對象或者調用的代碼。

    當然,Spring XML bean factories 有更多的功能沒有在這里描述,但是,應當讓你對基本使用有了一些感覺。以及,簡單的屬性,有JavaBean屬性編輯器的屬性,Spring可以自動處理lists,maps和java.util.Properties。

    Bean factories 和application contexts 通常和J2EE server定義的一個范圍相關聯,例如:


      Servlet context.:在spring 的MVC 框架里, 每一個包含common objects的web 應用都定義有一個應用程序的context。Spring提供了通過listener或者servlet實例化這樣的context的能力而不需要依賴于Spring 的MVC 框架,因而它也可以用于Struts,WebWork 或者其他的web框架之中。

      A Servlet:在Spring MVC 框架里每一個servlet控制器都有它自己的應用程序context,派生于根(全應用程序范圍的)應用程序context。在Struts或者其他MVC框架中實現這些也很容意。

      EJB:Spring 為EJB提供方便的超類,它們簡化了EJB的創建并且提供了一個從EJB Jar 文件中的XML文檔載入的BeanFactory。

    這些J2EE規范提供的hook通常避免了使用Singleton來創造一個bean factory。

    然而,如果我們愿意的話可以用代碼創建一個BeanFactory,雖然是沒有什么意義的。例如,我們在以下三行代碼中可以創建bean factory并且得到一個業務對象的引用:

    代碼:
    InputStream is = getClass().getResourceAsStream("myFile.xml");
    XmlBeanFactory bf = new XmlBeanFactory(is);
    MyBusinessObject mbo = (MyBusinessObject) bf.getBean("exampleBusinessObject");


    這段代碼將能工作在一個應用服務器之外:甚至不依賴J2EE,因為Spring 的IoC容器是純java的。

    posted on 2005-10-26 15:52 Sung 閱讀(207) 評論(0)  編輯  收藏 所屬分類: Java
    主站蜘蛛池模板: 亚洲成A∨人片天堂网无码| 亚洲色成人四虎在线观看| 国产又大又长又粗又硬的免费视频 | 国产亚洲精品无码成人| 国产美女被遭强高潮免费网站| 久久国产精品免费网站| 日本一区二区三区在线视频观看免费| 99999久久久久久亚洲| 亚洲国产AV无码专区亚洲AV| 亚洲综合精品网站| 国产乱弄免费视频| 久久久久国色AV免费看图片| 午夜免费1000部| 一区二区三区福利视频免费观看| 中文永久免费观看网站| 男女男精品网站免费观看| 亚洲av永久无码| 亚洲国产精品精华液| 亚洲综合丁香婷婷六月香| 久久亚洲精精品中文字幕| 亚洲福利在线视频| 久久亚洲精品成人| 久久精品7亚洲午夜a| 国产成人A人亚洲精品无码| 亚洲色大成网站WWW久久九九| 亚洲国产午夜中文字幕精品黄网站| 日韩成人在线免费视频| 国产成人免费永久播放视频平台 | 亚洲国产成人久久综合一区| 亚洲国产天堂久久综合网站| 亚洲国产精品无码久久SM| 亚洲AV无码久久精品成人| 亚洲韩国—中文字幕| 亚洲一区二区三区四区在线观看| 亚洲国产精品线在线观看| 亚洲高清美女一区二区三区| 亚洲毛片基地日韩毛片基地| 67194在线午夜亚洲| 国产精品亚洲综合久久| 欧美激情综合亚洲一二区| 污网站在线观看免费|