Introducing to Spring Framework 作者:Rod Johnson
譯者:yanger,taowen
校對(duì):taowen
關(guān)于Spring Framework,今年夏天你可能已經(jīng)聽(tīng)見(jiàn)很多的議論。在本文中,我將試圖解釋Spring能完成什么,和我怎么會(huì)認(rèn)為它能幫助你開(kāi)發(fā)J2EE應(yīng)用程序。
又來(lái)一個(gè)framework? 你可能正在想“不過(guò)是另外一個(gè)的framework”。當(dāng)已經(jīng)有許多開(kāi)放源代碼(和專(zhuān)有) J2EE framework時(shí),為什么你還要耐下心子讀這篇文章或去下載Spring Framework?
我相信Spring是獨(dú)特的,有幾個(gè)原因:
它關(guān)注的領(lǐng)域是其他許多流行的Framework未曾關(guān)注的。Spring要提供的是一種管理你的業(yè)務(wù)對(duì)象的方法。
Spring既是全面的又是模塊化的。Spring有分層的體系結(jié)構(gòu),這意味著你能選擇僅僅使用它任何一個(gè)獨(dú)立的部分,而它的架構(gòu)又是內(nèi)部一致。因此你能從你的學(xué)習(xí)中,得到最大的價(jià)值。例如,你可能選擇僅僅使用Spring來(lái)簡(jiǎn)單化JDBC的使用,或用來(lái)管理所有的業(yè)務(wù)對(duì)象。
它的設(shè)計(jì)從一開(kāi)始就是要幫助你編寫(xiě)易于測(cè)試的代碼。Spring是使用測(cè)試驅(qū)動(dòng)開(kāi)發(fā)的工程的理想框架。
Spring不會(huì)給你的工程添加對(duì)其他的框架依賴。Spring也許稱(chēng)得上是個(gè)一站式解決方案,提供了一個(gè)典型應(yīng)用所需要的大部分基礎(chǔ)架構(gòu)。它還涉及到了其他framework沒(méi)有考慮到的內(nèi)容。
盡管它僅僅是一個(gè)從2003年2月才開(kāi)始的開(kāi)源項(xiàng)目,但Spring有深厚的歷史根基。這個(gè)開(kāi)源工程是起源自我在2002年晚些時(shí)候出版的《Expert One-on-One J2EE設(shè)計(jì)與開(kāi)發(fā)》書(shū)中的基礎(chǔ)性代碼。這本書(shū)展示了Spring背后的基礎(chǔ)性架構(gòu)思想。然而,對(duì)這個(gè)基礎(chǔ)架構(gòu)的概念可以追溯到2000年的早些時(shí)候,并且反映了我為一系列商業(yè)工程開(kāi)發(fā)基礎(chǔ)結(jié)構(gòu)的成功經(jīng)驗(yàn)。
2003年1月,Spring已經(jīng)落戶于SourceForge上了。現(xiàn)在有10個(gè)開(kāi)發(fā)人員,其中6個(gè)是高度投入的積極分子。
Spring架構(gòu)上的好處 在我們進(jìn)入細(xì)節(jié)之前,讓我們來(lái)看看Spring能夠給工程帶來(lái)的種種好處:
Spring能有效地組織你的中間層對(duì)象,不管你是否選擇使用了EJB。如果你僅僅使用了Struts或其他為J2EE的 API特制的framework,Spring致力于解決剩下的問(wèn)題。
Spring能消除在許多工程中常見(jiàn)的對(duì)Singleton的過(guò)多使用。根據(jù)我的經(jīng)驗(yàn),這是一個(gè)很大的問(wèn)題,它降低了系統(tǒng)的可測(cè)試性和面向?qū)ο蟮某潭取?
通過(guò)一種在不同應(yīng)用程序和項(xiàng)目間一致的方法來(lái)處理配置文件,Spring能消除各種各樣自定義格式的屬性文件的需要。曾經(jīng)對(duì)某個(gè)類(lèi)要尋找的是哪個(gè)魔法般的屬性項(xiàng)或系統(tǒng)屬性感到不解,為此不得不去讀Javadoc甚至源編碼?有了Spring,你僅僅需要看看類(lèi)的JavaBean屬性。Inversion of Control的使用(在下面討論)幫助完成了這種簡(jiǎn)化。
通過(guò)把對(duì)接口編程而不是對(duì)類(lèi)編程的代價(jià)幾乎減少到?jīng)]有,Spring能夠促進(jìn)養(yǎng)成好的編程習(xí)慣。
Spring被設(shè)計(jì)為讓使用它創(chuàng)建的應(yīng)用盡可能少的依賴于他的APIs。在Spring應(yīng)用中的大多數(shù)業(yè)務(wù)對(duì)象沒(méi)有依賴于Spring。
使用Spring構(gòu)建的應(yīng)用程序易于單元測(cè)試。
Spring能使EJB的使用成為一個(gè)實(shí)現(xiàn)選擇,而不是應(yīng)用架構(gòu)的必然選擇。你能選擇用POJOs或local EJBs來(lái)實(shí)現(xiàn)業(yè)務(wù)接口,卻不會(huì)影響調(diào)用代碼。
Spring幫助你解決許多問(wèn)題而無(wú)需使用EJB。Spring能提供一種EJB的替換物,它們適用于許多web應(yīng)用。例如,Spring能使用AOP提供聲明性事務(wù)管理而不通過(guò)EJB容器,如果你僅僅需要與單個(gè)數(shù)據(jù)庫(kù)打交道,甚至不需要一個(gè)JTA實(shí)現(xiàn)。
Spring為數(shù)據(jù)存取提供了一個(gè)一致的框架,不論是使用的是JDBC還是O/R mapping產(chǎn)品(如Hibernate)。
Spring確實(shí)使你能通過(guò)最簡(jiǎn)單可行的解決辦法來(lái)解決你的問(wèn)題。而這是有有很大價(jià)值的。
Spring做了些什么? Spring提供許多功能,在此我將依次快速地展示其各個(gè)主要方面。
任務(wù)描述 首先,讓我們明確Spring范圍。盡管Spring覆蓋了許多方面,但我們對(duì)它應(yīng)該涉什么,什么不應(yīng)該涉及有清楚的認(rèn)識(shí)。
Spring的主要目的是使J2EE易用和促進(jìn)好編程習(xí)慣。
Spring不重新輪子。因此,你發(fā)現(xiàn)在Spring中沒(méi)有l(wèi)ogging,沒(méi)有連接池,沒(méi)有分布式事務(wù)調(diào)度。所有這些東西均有開(kāi)源項(xiàng)目提供(例如我們用于處理所有日志輸出的Commons Logging以及Commons DBCP),或由你的應(yīng)用程序服務(wù)器提供了。出于同樣的的原因,我們沒(méi)有提供O/R mapping層。對(duì)于這個(gè)問(wèn)題已經(jīng)有了像Hibernate和JDO這樣的優(yōu)秀解決方案。
Spring的目標(biāo)就是讓已有的技術(shù)更加易用。例如,盡管我們沒(méi)有底層事務(wù)協(xié)調(diào)處理,但我們提供了一個(gè)抽象層覆蓋了JTA或任何其他的事務(wù)策略。
Spring沒(méi)有直接和其他的開(kāi)源項(xiàng)目競(jìng)爭(zhēng),除非我們感到我們能提供新的一些東西。例如,象許多開(kāi)發(fā)人員一樣,我們從來(lái)沒(méi)有對(duì)Struts感到高興過(guò),并且覺(jué)得到在MVC web framework中還有改進(jìn)的余地。在某些領(lǐng)域,例如輕量級(jí)的IoC容器和AOP框架,Spring確實(shí)有直接的競(jìng)爭(zhēng),但是在這些領(lǐng)域還沒(méi)有已經(jīng)較為流行的解決方案。(Spring在這些領(lǐng)域是開(kāi)路先鋒。)
Spring也得益于內(nèi)在的一致性。所有的開(kāi)發(fā)者都在唱同樣的的贊歌,基礎(chǔ)想法依然與Expert One-on-One J2EE設(shè)計(jì)與開(kāi)發(fā)中提出的差不多。 并且我們已經(jīng)能夠在多個(gè)領(lǐng)域中使用一些中心的概念,例如Inversion of Control。
Spring在應(yīng)用服務(wù)器之間是可移植的。當(dāng)然保證可移植性總是一種挑戰(zhàn),但是我們避免使用任何平臺(tái)特有或非標(biāo)準(zhǔn)的東西,并且支持在WebLogic,Tomcat,Resin,JBoss,WebSphere和其他的應(yīng)用服務(wù)器上的用戶。
Inversion of Control 容器 Spring設(shè)計(jì)的核心是 org.springframework.beans 包, 它是為與JavaBeans一起工作而設(shè)計(jì)的。 這個(gè)包一般不直接被用戶使用,而是作為許多其他功能的基礎(chǔ)。
下一個(gè)層面高一些的抽象是"Bean Factory"。一個(gè)Spring bean factory 是一個(gè)通用的Factory,它使對(duì)象能夠按名稱(chēng)獲取,并且能管理對(duì)象之間的關(guān)系。
Bean factories 支持兩種模式的對(duì)象:
Singleton:在此模式中,有一個(gè)具有特定名稱(chēng)的共享對(duì)象實(shí)例,它在查找時(shí)被獲取。這是默認(rèn)的,而且是最為經(jīng)常使用的。它對(duì)于無(wú)狀態(tài)對(duì)象是一種理想的模式。
Prototype:在此模式中,每次獲取將創(chuàng)建一個(gè)獨(dú)立的對(duì)象。例如,這可以被用于讓用戶擁有他們自己的對(duì)象。
由于 org.springframwork.beans.factory.BeanFactory是一個(gè)簡(jiǎn)單的接口,它能被大量底層存儲(chǔ)方法實(shí)現(xiàn)。你能夠方便地實(shí)現(xiàn)你自己的BeanFactory,盡管很少用戶需要這么做。最為常用的BeanFactory定義是:
XmlBeanFactory: 可解析簡(jiǎn)單直觀的定義類(lèi)和命名對(duì)象屬性的XML結(jié)構(gòu)。 我們提供了一個(gè)DTD來(lái)使編寫(xiě)更容易。
ListableBeanFactoryImpl:提供了解析存放在屬性文件中的bean定義的能力,并且可通過(guò)編程創(chuàng)建BeanFactories。
每個(gè)bean定義可能是一個(gè)POJO(通過(guò)類(lèi)名和JavaBean初始屬性定義),或是一個(gè)FactoryBean。FactoryBean接口添加了一個(gè)間接層。通常,這用于創(chuàng)建使用AOP或其他方法的代理對(duì)象:例如,添加聲明性事務(wù)管理的代理。(這在概念上和EJB的interception相似,但實(shí)現(xiàn)得更簡(jiǎn)單。)
BeanFactories能在一個(gè)層次結(jié)構(gòu)中選擇性地參與,繼承ancestor(祖先)的定義。這使得在整個(gè)應(yīng)用中公共配置的共享成為可能,雖然個(gè)別資源,如controller servlets,還擁有他們自己的獨(dú)立的對(duì)象集合。
這種使用JavaBeans的動(dòng)機(jī)在《Expert One-on-One J2EE Design and Development》的第四章中有描述,在TheServerSide網(wǎng)站上的有免費(fèi)的PDF版本(http://www.theserverside.com/resources/article.jsp?l=RodJohnsonInterview)。
通過(guò)BeanFactory概念,Spring成為一個(gè)Inversion of Control的容器。(我不怎么喜歡container這個(gè)詞,因?yàn)樗谷寺?lián)想到重量級(jí)容器,如EJB容器。Spring的BeanFactory是一個(gè)可通過(guò)一行代碼創(chuàng)建的容器,并且不需要特殊的部署步驟。)
Inversion of Control背后的概念經(jīng)常表述為Hollywood原則的:“Don’t call me, I’ll call you。” IoC將控制創(chuàng)建的職責(zé)搬進(jìn)了框架中,并把它從應(yīng)用代碼脫離開(kāi)來(lái)。涉及到配置的地方,意思是說(shuō)在傳統(tǒng)的容器體系結(jié)構(gòu)中,如EJB,一個(gè)組件可以調(diào)用容器并問(wèn)“我需要它給我做工作的對(duì)象X在哪里?”;使用IoC容器則只需指出組件需要X對(duì)象,在運(yùn)行時(shí)容器會(huì)提供給它。容器是通過(guò)查看方法的參數(shù)表(例如JavaBean的屬性)做到的,也可能根據(jù)配置數(shù)據(jù)如XML。
IoC有幾個(gè)重要的好處,例如:
因?yàn)榻M件不需要在運(yùn)行時(shí)間尋找合作者,所以他們可以更簡(jiǎn)單的編寫(xiě)和維護(hù)。在Spring版的IoC里,組件通過(guò)暴露JavaBean的setter方法表達(dá)他們依賴的其他組件。這相當(dāng)于EJB通過(guò)JNDI來(lái)查找,EJB查找需要開(kāi)發(fā)人員編寫(xiě)代碼。
同樣原因,應(yīng)用代碼更容易測(cè)試。JavaBean屬性是簡(jiǎn)單的,屬于Java核心的,并且是容易測(cè)試的:僅編寫(xiě)一個(gè)自包含的Junit測(cè)試方法用來(lái)創(chuàng)建對(duì)象和設(shè)置相關(guān)屬性即可。
一個(gè)好的IoC實(shí)現(xiàn)保留了強(qiáng)類(lèi)型。如果你需要使用一個(gè)通用的factory來(lái)尋找合作者,你必須通過(guò)類(lèi)型轉(zhuǎn)換將返回結(jié)果轉(zhuǎn)變?yōu)橄胍念?lèi)型。這不是一個(gè)大不了的問(wèn)題,但是不雅觀。使用IoC,你在你的代碼中表達(dá)了強(qiáng)類(lèi)型依賴,框架將負(fù)責(zé)類(lèi)型轉(zhuǎn)換。這意味著在框架配置應(yīng)用時(shí),類(lèi)型不匹配將導(dǎo)致錯(cuò)誤;在你的代碼中,你無(wú)需擔(dān)心類(lèi)型轉(zhuǎn)換異常。
大部分業(yè)務(wù)對(duì)象不依賴于IoC容器的APIs。這使得很容易使用遺留下來(lái)的代碼,且很容易的使用對(duì)象無(wú)論在容器內(nèi)或不在容器內(nèi)。例如,Spring用戶經(jīng)常配置Jakarta Commons DBCP數(shù)據(jù)源為一個(gè)Spring bean:不需要些任何定制代碼去做這件事。我們說(shuō)一個(gè)IoC容器不是侵入性的:使用它并不會(huì)使你的代碼依賴于它的APIs。任何JavaBean在Spring bean factory中都能成為一個(gè)組件。
最后應(yīng)該強(qiáng)調(diào)的是,IoC 不同于傳統(tǒng)的容器的體系結(jié)構(gòu),如EJB,應(yīng)用代碼最小程度地依靠于容器。這意味著你的業(yè)務(wù)對(duì)象可以潛在的被運(yùn)行在不同的IoC 框架上——或者在任何框架之外——不需要任何代碼的改動(dòng)。
以我和其他Spring用戶的經(jīng)驗(yàn)來(lái)說(shuō),再怎么強(qiáng)調(diào)IoC給應(yīng)用程序代碼帶來(lái)的好處也不為過(guò)。
IoC不是一個(gè)新概念,但是它在J2EE團(tuán)體里面剛剛到達(dá)黃金時(shí)間。 有一些可供選擇的IoC 容器: 例如 Apache Avalon, PicoContainer 和 HiveMind。Avalon 從沒(méi)怎么流行,盡管它很強(qiáng)大而且有很長(zhǎng)的歷史。Avalon相當(dāng)?shù)闹睾蛷?fù)雜,并且看起來(lái)比新的IoC解決方案更具侵入性。 PicoContainer是一個(gè)輕量級(jí)而且更強(qiáng)調(diào)通過(guò)構(gòu)造函數(shù)表達(dá)依賴性而不是JavaBean 屬性。 與Spring不同,它的設(shè)計(jì)允許每個(gè)類(lèi)型一個(gè)對(duì)象的定義(可能是因?yàn)樗芙^任何Java代碼外的元數(shù)據(jù)導(dǎo)致的局限性)。在Spring, PicoContainer 和其他 IoC frameworks之間做比較,可參看文章Spring網(wǎng)站上的"The Spring Framework - A Lightweight Container"位于http://www.springframework.org/docs/lightweight_container.html。這個(gè)頁(yè)面里面包含了PicoContainer站點(diǎn)的鏈接 。
Spring BeanFactories 是非常輕量級(jí)的。用戶已經(jīng)成功地將他們應(yīng)用在applets和單獨(dú)的Swing應(yīng)用中。(它們也很好地工作在EJB容器中。) 沒(méi)有特殊的部署步驟和察覺(jué)得到的啟動(dòng)時(shí)間。這個(gè)能力表明一個(gè)容器在應(yīng)用的任何層面幾乎立即可以發(fā)揮非常大的價(jià)值。
Spring BeanFactory 概念貫穿于Spring始終, 而且是Spring如此內(nèi)在一致的關(guān)鍵原因。在IoC容器中,Spring也是唯一的,它使用IoC作為基礎(chǔ)概念貫穿于整個(gè)功能豐富的框架。
對(duì)應(yīng)用開(kāi)發(fā)人員,最重要的是,一個(gè)或多個(gè)BeanFactory提供了一個(gè)定義明確的業(yè)務(wù)對(duì)象層。這類(lèi)似于local session bean層,但比它更簡(jiǎn)單。與EJBs不同,在這個(gè)層中的對(duì)象可能是相關(guān)的,并且他們的關(guān)系被擁有它們的factory管理。有一個(gè)定義明確的業(yè)務(wù)對(duì)象層對(duì)于成功的體系結(jié)構(gòu)是非常重要的。
Spring ApplicationContext 是BeanFactory的子接口,為下列東西提供支持:
信息查找,支持著國(guó)際化
事件機(jī)制,允許發(fā)布應(yīng)用對(duì)象以及可選的注冊(cè)以接收到事件
可移植的文件和資源訪問(wèn)
XmlBeanFactory 例子 Spring用戶通常在XML的“bean定義”文件中配置他們的應(yīng)用。Spring的XML bean定義文檔的根是<beans> 元素。該元素包含一個(gè)或多個(gè) <bean>定義。我們一般給每個(gè)bean定義的指定類(lèi)和屬性。我們還必須指定ID作為標(biāo)識(shí),這將成為在代碼中使用該bean的名字。
讓我們來(lái)看一個(gè)簡(jiǎn)單的例子,它配置了三個(gè)應(yīng)用程序?qū)ο螅g的關(guān)系在J2EE應(yīng)用中常常能夠看到:
J2EE DataSource
使用DataSource的DAO
在處理過(guò)程中使用DAO的業(yè)務(wù)對(duì)象
在下面的例子中,我們使用一個(gè)來(lái)自Jakarta Commons DBCP項(xiàng)目的BasicDataSource。這個(gè)class(和其他許多已有的class一樣)可以簡(jiǎn)單地被應(yīng)用在Spring bean factory中,只要它提供了JavaBean格式的配置。需要在shutdown時(shí)被調(diào)用的Close方法可通過(guò)Spring的"destroy-method"屬性被注冊(cè),以避免BasicDataSource需要實(shí)現(xiàn)任何Spring 的接口。
java代碼: |
<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類(lèi)型的,因此我們用<value>元素來(lái)指定他們的值。如果必要的話,Spring使用標(biāo)準(zhǔn)的 JavaBean屬性編輯器機(jī)制來(lái)把String轉(zhuǎn)換為其他的類(lèi)型。
現(xiàn)在,我們定義DAO,它有一個(gè)對(duì)DataSource的bean引用。Bean間關(guān)系通過(guò)<ref>元素來(lái)指定:
java代碼: |
<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>
|
對(duì)象間的關(guān)系一般在配置中明確地設(shè)置,象這個(gè)例子一樣。我們認(rèn)為這樣做是件好事情。然而Spring還提供了我們稱(chēng)做"autowire"的支持, 一個(gè)la PicoContainer,其中它指出了bean間的依賴關(guān)系。這樣做的局限性——PicoContainer也是如此——是如果有一個(gè)特殊類(lèi)型的多個(gè)Bean,要確定那個(gè)類(lèi)型所依賴的是哪個(gè)實(shí)例是不可能。好的方面是,不滿足的依賴可以在factory初始化后被捕獲到。(Spring 也為顯式的配置提供了一種可選的依賴檢查,它可以完成這個(gè)目的)
在上面的例子中,如果我們不想顯式的編寫(xiě)他們的關(guān)系,可使用如下的autowire特性:
java代碼: |
<bean id="exampleBusinessObject" class="example.ExampleBusinessObject" autowire="byType">
<property name="exampleParam"><value>10</value></property> </bean>
|
使用這個(gè)特性,Spring會(huì)找出exampleBusinessObject的dataSource屬性應(yīng)該被設(shè)置為在當(dāng)前BeanFactory中找到的DataSource實(shí)現(xiàn)。在當(dāng)前的BeanFactory中,如果所需要類(lèi)型的bean不存在或多于一個(gè),將產(chǎn)生一個(gè)錯(cuò)誤。我們依然要設(shè)置exampleParam屬性,因?yàn)樗皇且粋€(gè)引用。
Autowire支持和依賴檢查剛剛加入CVS并將在Spring 1.0 M2(到10/20,2003)中提供。本文中所討論的所有其他特性都包含在當(dāng)前1.0 M1版本中。
把管理從Java代碼中移出來(lái)比硬編碼有很大的好處,因?yàn)檫@樣可以只改變XML文件而無(wú)需改變一行Java代碼。例如,我們可以簡(jiǎn)單地改變myDataSource的bean定義引用不同的bean class以使用別的連接池,或者一個(gè)用于測(cè)試的數(shù)據(jù)源。 XML節(jié)變成另一種,我們可以用Spring的JNDI location FactoryBean從應(yīng)用服務(wù)器獲取一個(gè)數(shù)據(jù)源。
現(xiàn)在讓我們來(lái)看看例子中業(yè)務(wù)對(duì)象的java 代碼。注意下面列出的代碼中沒(méi)有對(duì)Spring的依賴。不像EJB容器,Spring BeanFactory不具有侵入性:在應(yīng)用對(duì)象里面你通常不需要對(duì)Spring的存在硬編碼。
java代碼: |
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,它們對(duì)應(yīng)于bean定義文檔中的XML引用。這些將在對(duì)象被使用之前由Spring調(diào)用。
這些應(yīng)用程序的bean不需要依賴于Spring:他們不需要實(shí)現(xiàn)任何Spring的接口或者繼承Spring的類(lèi)。他們只需要遵守JavaBeans的命名習(xí)慣。在Spring 應(yīng)用環(huán)境之外重用它們是非常簡(jiǎn)單的,例如,在一個(gè)測(cè)試環(huán)境中。只需要用它們的缺省構(gòu)造函數(shù)實(shí)例化它們,并且通過(guò)調(diào)用setDataSource()和setExampleParam()手工設(shè)置它的屬性。如果你想以一行代碼支持程序化的創(chuàng)建,只要你有一個(gè)無(wú)參數(shù)的構(gòu)造器,你就可以自由定義其他需要多個(gè)屬性的構(gòu)造函數(shù)。
注意在業(yè)務(wù)接口中沒(méi)有聲明將會(huì)一起使用的JavaBean屬性。 他們是一個(gè)實(shí)現(xiàn)細(xì)節(jié)。我們可以“插入”帶有不同bean屬性的不同的實(shí)現(xiàn)類(lèi)而不影響連接著的對(duì)象或者調(diào)用的代碼。
當(dāng)然,Spring XML bean factories 有更多的功能沒(méi)有在這里描述,但是,應(yīng)當(dāng)讓你對(duì)基本使用有了一些感覺(jué)。以及,簡(jiǎn)單的屬性,有JavaBean屬性編輯器的屬性,Spring可以自動(dòng)處理lists,maps和java.util.Properties。
Bean factories 和application contexts 通常和J2EE server定義的一個(gè)范圍相關(guān)聯(lián),例如:
Servlet context.:在spring 的MVC 框架里, 每一個(gè)包含common objects的web 應(yīng)用都定義有一個(gè)應(yīng)用程序的context。Spring提供了通過(guò)listener或者servlet實(shí)例化這樣的context的能力而不需要依賴于Spring 的MVC 框架,因而它也可以用于Struts,WebWork 或者其他的web框架之中。
A Servlet:在Spring MVC 框架里每一個(gè)servlet控制器都有它自己的應(yīng)用程序context,派生于根(全應(yīng)用程序范圍的)應(yīng)用程序context。在Struts或者其他MVC框架中實(shí)現(xiàn)這些也很容意。
EJB:Spring 為EJB提供方便的超類(lèi),它們簡(jiǎn)化了EJB的創(chuàng)建并且提供了一個(gè)從EJB Jar 文件中的XML文檔載入的BeanFactory。
這些J2EE規(guī)范提供的hook通常避免了使用Singleton來(lái)創(chuàng)造一個(gè)bean factory。
然而,如果我們?cè)敢獾脑捒梢杂么a創(chuàng)建一個(gè)BeanFactory,雖然是沒(méi)有什么意義的。例如,我們?cè)谝韵氯写a中可以創(chuàng)建bean factory并且得到一個(gè)業(yè)務(wù)對(duì)象的引用:
java代碼: |
InputStream is = getClass().getResourceAsStream("myFile.xml"); XmlBeanFactory bf = new XmlBeanFactory(is); MyBusinessObject mbo = (MyBusinessObject) bf.getBean("exampleBusinessObject");
|
這段代碼將能工作在一個(gè)應(yīng)用服務(wù)器之外:甚至不依賴J2EE,因?yàn)镾pring 的IoC容器是純java的。