作者注:在《Better, Faster, Lighter Java》一書第八章的這份節(jié)錄中,我們將看到一個使用Spring框架的企業(yè)web應(yīng)用程序例子。盡管Hibernate提供了單個的服務(wù),Spring框架卻提供了一種高效地構(gòu)建和匯編Java應(yīng)用程序的方法,以及多種服務(wù)的抽象。盡管 Spring支持多種服務(wù),但是它最受關(guān)注也是最出色的特性是杰出的分層和封裝。與EJB一樣,Spring的中心組件是一個容器;而且Spring框架也同樣提供對核心J2EE服務(wù)的訪問。但是這就是它們僅有的相似之處了。下面是一個比喻。
我喜歡皮劃艇運(yùn)動,也花了很多時間來教授皮劃艇技巧。我的一個專長就是教授學(xué)生如何在浪花中翻轉(zhuǎn)弄翻了的皮劃艇。一天,我向一位四肢發(fā)達(dá)的大個子和一位玲瓏瘦小、體重只有97磅的女士傳授該技巧。當(dāng)我在陸地上從頭到尾仔細(xì)地講述這項技巧的時候,大個子直勾勾的盯著遠(yuǎn)方,不感興趣。而那位女士注意力集中,而且希望反復(fù)練習(xí)這項基礎(chǔ)技巧。在半個小時之內(nèi),她就出色地完成了第一次翻轉(zhuǎn),而他只是上下?lián)u擺,在平靜的水面上拍打出細(xì)小的白色泡沫。直到第三個學(xué)時,他才完成這個動作。在以后的幾個學(xué)時中,她依靠技巧快速提高,而他卻單憑力量在水中掙扎。到了實踐的時候,她翻轉(zhuǎn)了皮劃艇,而他卻在游泳。程序員們,請記住:解決問題的最佳方式是依靠簡單性和技巧,而不是蠻力。
Pet Store:一個反例
Pet Store J2EE應(yīng)用程序是一個很糟糕的編程例子。它誤導(dǎo)成千上萬名J2EE開發(fā)人員構(gòu)建出設(shè)計糟糕、性能低下的代碼。它還是一個基準(zhǔn)的爭論焦點。 Middleware Company致力于制訂比較J2EE和微軟的.NET平臺的基準(zhǔn)。他們選擇Pet Store的J2EE版本作為基準(zhǔn)的基礎(chǔ)。盡管他們很努力地調(diào)優(yōu),J2EE版本還是慘敗給Microsoft .NET版本,因此導(dǎo)致J2EE設(shè)計備受批評。我不想針對這次慘敗譴責(zé)什么。我有不同的看法。我堅持認(rèn)為:利用J2EE(尤其是EJB)很難開發(fā)出整潔、高性能的代碼。另一方面,Pet Store基準(zhǔn)本身就會導(dǎo)致更大的問題。
基準(zhǔn)紛爭過后,很多人借助于更平易且更簡單的技術(shù)來實現(xiàn)Pet Store。其中一種最強(qiáng)大且最簡單的實現(xiàn)方法是Clinton Begin所使用的,他利用一個稱為iBatis的DAO框架來代替全部的實體bean。Rod Johnson的團(tuán)隊將該應(yīng)用程序轉(zhuǎn)化為Spring,并且現(xiàn)在已經(jīng)與Spring框架一起發(fā)布。以下是相關(guān)的一些細(xì)節(jié):
在下面的部分中,我將演示具有MVC web前端和單個數(shù)據(jù)庫中的簡單事務(wù)的應(yīng)用程序版本。我將重點討論域模型、單數(shù)據(jù)庫DAO層、單一事務(wù)以及Spring MVC前端。Spring網(wǎng)站上提供了大量的資源,可供希望深入研究的開發(fā)人員使用。
配置文件
了解Spring應(yīng)用程序應(yīng)當(dāng)從配置文件開始,它顯示了主要的bean以及應(yīng)用程序如何將它們組合在一起。Spring配置文件在應(yīng)用程序上下文中定義bean。將上下文看作是收集應(yīng)用程序指定資源的一種便利方式。
很多J2EE應(yīng)用程序借助單元素來了解諸如連接之類的應(yīng)用程序資源。這種用途的單元素與很多Java開發(fā)人員經(jīng)常使用的全局變量差別不大。 J2EE中的替代方案是一種稱為JNDI的目錄服務(wù),但是對于許多常見用例來說它就是殺雞的牛刀了。而Spring使用一種應(yīng)用程序上下文。最初,需要在一個簡單的XML文件中指定應(yīng)用程序上下文,盡管也可以通過擴(kuò)展Spring來接受其它類型的配置文件。以下是應(yīng)用程序上下文中可能會包含的內(nèi)容:
數(shù)據(jù)源
管理連接的Java類,通常在一個池中。
DAO層
如果應(yīng)用程序使用了數(shù)據(jù)庫,那么很可能需要隔離對DAO層數(shù)據(jù)庫的訪問。可以通過應(yīng)用程序上下文來訪問該層。
持久性管理器
每個持久性框架都有一個應(yīng)用程序用來訪問其特性的對象或工廠。對于Hibernate來說,它就是會話和會話工廠。而對于JDO來說,它就是持久性管理器工廠和持久性管理器。
事務(wù)策略
可以顯式地聲明希望在事務(wù)中使用的方法以及用于實施該策略的事務(wù)管理器。
事務(wù)管理器
J2EE中有很多不同的事務(wù)管理策略。對于單一數(shù)據(jù)庫的應(yīng)用程序,Spring允許使用數(shù)據(jù)庫的事務(wù)管理。對于多個數(shù)據(jù)庫或事務(wù)源,Spring允許使用JTA。可以將事務(wù)管理器保存在應(yīng)用程序上下文中。
驗證邏輯
Spring框架使用一種與Strut類似的驗證框架。Spring允許像配置其他業(yè)務(wù)組件那樣配置驗證邏輯。
視圖和控制器
Spring框架允許為視圖指定控制器,并幫助用戶通過控制器來配置導(dǎo)航路徑。
jPetStore應(yīng)用程序使用包含一個數(shù)據(jù)源、DAO層和一種事務(wù)邏輯的Spring應(yīng)用程序上下文。用戶定義XML文檔中上下文的內(nèi)容,該 XML文檔列出了一系列bean。每一個XML配置文件都包含一個<beans>題頭,其后是一系列<bean>組件和一個 </beans>腳注。如下所示:
以上是構(gòu)成應(yīng)用程序上下文的bean。它們代表應(yīng)用程序中的頂級bean。(它們可以創(chuàng)建不出現(xiàn)在配置文件中的其他對象或bean。)在本例中,我們會創(chuàng)建兩個bean:MyFirstBean和MySecondBean。然后,通過指定MySecondBean作為字段myField的值,將它們關(guān)聯(lián)起來。當(dāng)Spring啟動的時候,它會創(chuàng)建兩種對象,并設(shè)置myField的值。當(dāng)在應(yīng)用程序上下文中需要它們的時候,可以根據(jù)名稱來訪問這兩種對象。
我們來看一個更具體的實例。jPetStore應(yīng)用程序為業(yè)務(wù)邏輯、數(shù)據(jù)層和用戶界面提供了三種配置文件,每種Spring配置文件各自描述三者之一,如圖8-2所示。
圖8-2 jPetStore應(yīng)用程序提供了分別與三個不同的層相匹配的Spring應(yīng)用程序上下文
這些配置文件指定了域模型、數(shù)據(jù)層和表示層的上下文。例8-1展示了jPetStore應(yīng)用程序的業(yè)務(wù)邏輯應(yīng)用程序上下文的一部分。注意:為了簡單起見,我將包名org.springframework.samples.jpetstore...縮寫為jpetstore。
例8-1 applicationContext.xml
以下是對注釋的解釋:
[1]業(yè)務(wù)邏輯。這部分(包括所有粗體代碼)包含核心的業(yè)務(wù)邏輯。驗證和域模型都視為業(yè)務(wù)組件。
[2]驗證器。這是Order的驗證器。一旦用戶提交Order格式,并發(fā)送到錯誤頁面或order完成頁面,Spring就會按照要求調(diào)用該驗證器。
[3]核心業(yè)務(wù)實現(xiàn)。該類包含持久性域模型的核心實現(xiàn)。它包含以下所有的DAO對象。
[4]屬性。每一個bean都具有自己的屬性,這些屬性引用定義在其他地方的bean。在本例中,bean屬性是單個的DAO。每一個bean都定義在另一個Spring配置文件中。
[5]事務(wù)聲明。這個bean指定了應(yīng)用程序的事務(wù)策略。在本例中,應(yīng)用程序使用在另一個Spring配置文件中指定的事務(wù)管理器。它聲明了應(yīng)當(dāng)傳播為事務(wù)的方法。例如,所有以insert開頭的方法應(yīng)當(dāng)傳播為事務(wù)。
簡而言之,該配置文件就像一種粘合劑,將應(yīng)用程序的業(yè)務(wù)邏輯粘合在一起。在文件中,您會看到一些對本身并未包含在配置文件中的bean(如: DAO對象)的引用。隨后,您會看到其他兩種配置文件,它們定義了一些遺漏的bean。其中一個配置文件指定了事務(wù)管理器的數(shù)據(jù)訪問對象。另一個配置文件指定了用戶界面所需的bean。最好將配置文件分離到不同的層中,這樣就可以按照需要配置各個層。例如,可能需要更改用戶界面的策略(比如從Spring MVC web更改為Strut),或者數(shù)據(jù)訪問的策略(比如從具有單個數(shù)據(jù)庫的DAO更改為具有JTA事務(wù)、跨兩個數(shù)據(jù)庫的DAO)。
如果需要實例化XML上下文文件中的bean,那么非常簡單。例如,要訪問context.xml文件中Customer類型的名稱為myCustomer的bean,可以采用以下三個步驟:
1, 獲取包含配置的XML文件的輸入流:
2,使用輸入流創(chuàng)建新的Spring bean工廠:
3, 使用該工廠創(chuàng)建.xml文件中定義的一個對象:
或者,如果希望Spring初始化一個上下文,然后抓取會話外觀,可以使用以下代碼:
最好放開控制權(quán)。通常不必直接訪問應(yīng)用程序上下文。框架會執(zhí)行該操作。例如,如果您正在使用servlet,那么Spring框架會為每一個 servlet提供一個上下文,并為所有servlet提供一個總體上下文。通常可以從中獲得正確的上下文信息,隨后您就會看到這一點。既然已經(jīng)看到了表示jPetStore應(yīng)用程序的配置文件,現(xiàn)在應(yīng)該看看如何構(gòu)建各個元素:
域模型
與本書闡述的原理相對應(yīng),該應(yīng)用程序以圖8-3中的透明域模型為基礎(chǔ)。該域模型包含表示現(xiàn)實世界的各個對象之間的業(yè)務(wù)關(guān)系。Pet Store由包含項目的cart(購物車)和order(訂單)組成。
圖8-3 應(yīng)用程序的中心是域模型。
應(yīng)用程序表示了一個簡單的寵物商店。它由一個包含購物車項目(cart item)的購物車組成,該購物車又填充了一個包含線項目(line item)的訂單。項目(item)由按類別(category)組織的產(chǎn)品(product)組成。每個對象都是一個透明的業(yè)務(wù)對象,被實現(xiàn)為具有一些屬性和業(yè)務(wù)方法的Java bean。例8-2展示了一個CartItem。為了簡單起見,我已經(jīng)去掉導(dǎo)入和包細(xì)節(jié)。
例8-2CartItem.java
以下是注釋的含義:
[1]Spring框架不會強(qiáng)迫組件繼承Spring類。它們是完全透明的,并且如果進(jìn)行測試或者情況需要,還可以駐留在容器的外部。
[2]每一個字段都使用get和set方法進(jìn)行包裝,以便Spring可以通過Java反射來配置他們。(Spring還可以通過構(gòu)造函數(shù)來配置它們。)
[3]與很多EJB應(yīng)用程序不同,在域模型中包含業(yè)務(wù)域邏輯非常有用。
我將這種模型稱作passive。它完全由域外面的對象調(diào)用,并且僅與域中的其他對象耦合。注意,雖然它具有私有屬性和公有字段,但是它不僅僅是一個值對象。它包含用于計算總價和增加數(shù)量的業(yè)務(wù)方法。這種設(shè)計使得該業(yè)務(wù)對象易于理解和重用,即使是在整體設(shè)計改進(jìn)的情況下。當(dāng)我們介紹持久性方面時,您就會看到該模型的其他部分。
下周,在這個摘錄自《Better, Faster, Lighter Java》一書的Spring系列的最后一部分中,作者將講述如何將持久性添加到Pet Store例子中,并討論Spring框架中的表示邏輯。
原文出處: Demonstrating Spring's Finesse http://www.onjava.com/pub/a/onjava/excerpt/BFLJava_chap8/index.html
作者簡介
Bruce A.ate是一名山地車手和皮劃艇手,也是2個孩子的父親。在閑暇時間里,他還是一名獨(dú)立顧問。他住在德克薩斯州的首府奧斯汀。他編寫了4本書,其中包括最暢銷的《Bitter Java》一書,最近出版了《Better,Faster,Lighter Java》(O'Reilly)。
Alexander Ananiev是一個程序員、作者、導(dǎo)師和指導(dǎo)員,他專攻現(xiàn)實世界軟件應(yīng)用程序。
我喜歡皮劃艇運(yùn)動,也花了很多時間來教授皮劃艇技巧。我的一個專長就是教授學(xué)生如何在浪花中翻轉(zhuǎn)弄翻了的皮劃艇。一天,我向一位四肢發(fā)達(dá)的大個子和一位玲瓏瘦小、體重只有97磅的女士傳授該技巧。當(dāng)我在陸地上從頭到尾仔細(xì)地講述這項技巧的時候,大個子直勾勾的盯著遠(yuǎn)方,不感興趣。而那位女士注意力集中,而且希望反復(fù)練習(xí)這項基礎(chǔ)技巧。在半個小時之內(nèi),她就出色地完成了第一次翻轉(zhuǎn),而他只是上下?lián)u擺,在平靜的水面上拍打出細(xì)小的白色泡沫。直到第三個學(xué)時,他才完成這個動作。在以后的幾個學(xué)時中,她依靠技巧快速提高,而他卻單憑力量在水中掙扎。到了實踐的時候,她翻轉(zhuǎn)了皮劃艇,而他卻在游泳。程序員們,請記住:解決問題的最佳方式是依靠簡單性和技巧,而不是蠻力。
Pet Store:一個反例
Pet Store J2EE應(yīng)用程序是一個很糟糕的編程例子。它誤導(dǎo)成千上萬名J2EE開發(fā)人員構(gòu)建出設(shè)計糟糕、性能低下的代碼。它還是一個基準(zhǔn)的爭論焦點。 Middleware Company致力于制訂比較J2EE和微軟的.NET平臺的基準(zhǔn)。他們選擇Pet Store的J2EE版本作為基準(zhǔn)的基礎(chǔ)。盡管他們很努力地調(diào)優(yōu),J2EE版本還是慘敗給Microsoft .NET版本,因此導(dǎo)致J2EE設(shè)計備受批評。我不想針對這次慘敗譴責(zé)什么。我有不同的看法。我堅持認(rèn)為:利用J2EE(尤其是EJB)很難開發(fā)出整潔、高性能的代碼。另一方面,Pet Store基準(zhǔn)本身就會導(dǎo)致更大的問題。
基準(zhǔn)紛爭過后,很多人借助于更平易且更簡單的技術(shù)來實現(xiàn)Pet Store。其中一種最強(qiáng)大且最簡單的實現(xiàn)方法是Clinton Begin所使用的,他利用一個稱為iBatis的DAO框架來代替全部的實體bean。Rod Johnson的團(tuán)隊將該應(yīng)用程序轉(zhuǎn)化為Spring,并且現(xiàn)在已經(jīng)與Spring框架一起發(fā)布。以下是相關(guān)的一些細(xì)節(jié):
- Spring jPetStore應(yīng)用程序包含在M4或更高版本的Spring中。
- 它是一種具有JDBC DAO層的數(shù)據(jù)驅(qū)動的應(yīng)用程序。
- 它提供了Strut的替代前端以及Spring MVC框架。
- 它提供了兩種不同的模型。最簡單的模型使用單一數(shù)據(jù)庫和簡單JDBC事務(wù)。另一種模型可以跨多個數(shù)據(jù)庫使用JTA事務(wù)管理。
在下面的部分中,我將演示具有MVC web前端和單個數(shù)據(jù)庫中的簡單事務(wù)的應(yīng)用程序版本。我將重點討論域模型、單數(shù)據(jù)庫DAO層、單一事務(wù)以及Spring MVC前端。Spring網(wǎng)站上提供了大量的資源,可供希望深入研究的開發(fā)人員使用。
配置文件
了解Spring應(yīng)用程序應(yīng)當(dāng)從配置文件開始,它顯示了主要的bean以及應(yīng)用程序如何將它們組合在一起。Spring配置文件在應(yīng)用程序上下文中定義bean。將上下文看作是收集應(yīng)用程序指定資源的一種便利方式。
很多J2EE應(yīng)用程序借助單元素來了解諸如連接之類的應(yīng)用程序資源。這種用途的單元素與很多Java開發(fā)人員經(jīng)常使用的全局變量差別不大。 J2EE中的替代方案是一種稱為JNDI的目錄服務(wù),但是對于許多常見用例來說它就是殺雞的牛刀了。而Spring使用一種應(yīng)用程序上下文。最初,需要在一個簡單的XML文件中指定應(yīng)用程序上下文,盡管也可以通過擴(kuò)展Spring來接受其它類型的配置文件。以下是應(yīng)用程序上下文中可能會包含的內(nèi)容:
數(shù)據(jù)源
管理連接的Java類,通常在一個池中。
DAO層
如果應(yīng)用程序使用了數(shù)據(jù)庫,那么很可能需要隔離對DAO層數(shù)據(jù)庫的訪問。可以通過應(yīng)用程序上下文來訪問該層。
持久性管理器
每個持久性框架都有一個應(yīng)用程序用來訪問其特性的對象或工廠。對于Hibernate來說,它就是會話和會話工廠。而對于JDO來說,它就是持久性管理器工廠和持久性管理器。
事務(wù)策略
可以顯式地聲明希望在事務(wù)中使用的方法以及用于實施該策略的事務(wù)管理器。
事務(wù)管理器
J2EE中有很多不同的事務(wù)管理策略。對于單一數(shù)據(jù)庫的應(yīng)用程序,Spring允許使用數(shù)據(jù)庫的事務(wù)管理。對于多個數(shù)據(jù)庫或事務(wù)源,Spring允許使用JTA。可以將事務(wù)管理器保存在應(yīng)用程序上下文中。
驗證邏輯
Spring框架使用一種與Strut類似的驗證框架。Spring允許像配置其他業(yè)務(wù)組件那樣配置驗證邏輯。
視圖和控制器
Spring框架允許為視圖指定控制器,并幫助用戶通過控制器來配置導(dǎo)航路徑。
jPetStore應(yīng)用程序使用包含一個數(shù)據(jù)源、DAO層和一種事務(wù)邏輯的Spring應(yīng)用程序上下文。用戶定義XML文檔中上下文的內(nèi)容,該 XML文檔列出了一系列bean。每一個XML配置文件都包含一個<beans>題頭,其后是一系列<bean>組件和一個 </beans>腳注。如下所示:
代碼: |
<beans> <bean id="MyFirstBean" class="package.MyFirstBeanClass"> <property name="myField" ref local="MySecondBean"/> </bean> <bean id="MySecondBean" class="package.MySecondBeanClass"> </bean> </beans> |
以上是構(gòu)成應(yīng)用程序上下文的bean。它們代表應(yīng)用程序中的頂級bean。(它們可以創(chuàng)建不出現(xiàn)在配置文件中的其他對象或bean。)在本例中,我們會創(chuàng)建兩個bean:MyFirstBean和MySecondBean。然后,通過指定MySecondBean作為字段myField的值,將它們關(guān)聯(lián)起來。當(dāng)Spring啟動的時候,它會創(chuàng)建兩種對象,并設(shè)置myField的值。當(dāng)在應(yīng)用程序上下文中需要它們的時候,可以根據(jù)名稱來訪問這兩種對象。
我們來看一個更具體的實例。jPetStore應(yīng)用程序為業(yè)務(wù)邏輯、數(shù)據(jù)層和用戶界面提供了三種配置文件,每種Spring配置文件各自描述三者之一,如圖8-2所示。

圖8-2 jPetStore應(yīng)用程序提供了分別與三個不同的層相匹配的Spring應(yīng)用程序上下文
這些配置文件指定了域模型、數(shù)據(jù)層和表示層的上下文。例8-1展示了jPetStore應(yīng)用程序的業(yè)務(wù)邏輯應(yīng)用程序上下文的一部分。注意:為了簡單起見,我將包名org.springframework.samples.jpetstore...縮寫為jpetstore。
例8-1 applicationContext.xml
代碼: |
<beans> [1] <bean id="accountValidator" class="jpetstore.domain.logic.AccountValidator"/> [2] <bean id="orderValidator" class="jpetstore.domain.logic.OrderValidator"/> [3] <bean id="petStoreTarget" class="jpetstore.domain.logic.PetStoreImpl"/> [4] <property name="AccountDao"><ref bean="accountDao"/></property> <property name="categoryDao"><ref bean="categoryDao"/></property> <property name="productDao"><ref bean="productDao"/></property> <property name="itemDao"><ref bean="itemDao"/></property> <property name="orderDao"><ref bean="orderDao"/></property> </bean> [5] <bean id="petStore" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean"> <property name="transactionManager"><ref bean="transactionManager"/></property> <property name="target"><ref bean="petStoreTarget"/></property> <property name="transactionAttributes"> <props> <prop key="insert*">PROPAGATION_REQUIRED</prop> <prop key="update*">PROPAGATION_REQUIRED</prop> <prop key="*">PROPAGATION_REQUIRED,readOnly</prop> </props> </property> </bean> </beans> |
以下是對注釋的解釋:
[1]業(yè)務(wù)邏輯。這部分(包括所有粗體代碼)包含核心的業(yè)務(wù)邏輯。驗證和域模型都視為業(yè)務(wù)組件。
[2]驗證器。這是Order的驗證器。一旦用戶提交Order格式,并發(fā)送到錯誤頁面或order完成頁面,Spring就會按照要求調(diào)用該驗證器。
[3]核心業(yè)務(wù)實現(xiàn)。該類包含持久性域模型的核心實現(xiàn)。它包含以下所有的DAO對象。
[4]屬性。每一個bean都具有自己的屬性,這些屬性引用定義在其他地方的bean。在本例中,bean屬性是單個的DAO。每一個bean都定義在另一個Spring配置文件中。
[5]事務(wù)聲明。這個bean指定了應(yīng)用程序的事務(wù)策略。在本例中,應(yīng)用程序使用在另一個Spring配置文件中指定的事務(wù)管理器。它聲明了應(yīng)當(dāng)傳播為事務(wù)的方法。例如,所有以insert開頭的方法應(yīng)當(dāng)傳播為事務(wù)。
簡而言之,該配置文件就像一種粘合劑,將應(yīng)用程序的業(yè)務(wù)邏輯粘合在一起。在文件中,您會看到一些對本身并未包含在配置文件中的bean(如: DAO對象)的引用。隨后,您會看到其他兩種配置文件,它們定義了一些遺漏的bean。其中一個配置文件指定了事務(wù)管理器的數(shù)據(jù)訪問對象。另一個配置文件指定了用戶界面所需的bean。最好將配置文件分離到不同的層中,這樣就可以按照需要配置各個層。例如,可能需要更改用戶界面的策略(比如從Spring MVC web更改為Strut),或者數(shù)據(jù)訪問的策略(比如從具有單個數(shù)據(jù)庫的DAO更改為具有JTA事務(wù)、跨兩個數(shù)據(jù)庫的DAO)。
如果需要實例化XML上下文文件中的bean,那么非常簡單。例如,要訪問context.xml文件中Customer類型的名稱為myCustomer的bean,可以采用以下三個步驟:
1, 獲取包含配置的XML文件的輸入流:
代碼: |
InputStream stream = getClass( ). getResourceAsStream("context.xml"); |
2,使用輸入流創(chuàng)建新的Spring bean工廠:
代碼: |
XmlBeanFactory beanFactory = new XmlBeanFactory(stream); |
3, 使用該工廠創(chuàng)建.xml文件中定義的一個對象:
代碼: |
Customer cust = (Customer)beanFactory.getBean(myCustomer); |
或者,如果希望Spring初始化一個上下文,然后抓取會話外觀,可以使用以下代碼:
代碼: |
protected static final String CONTEXT_FILE = "WEB-INF/applicationContext.xml"; Biz biz; // session fa?ade FileSystemXmlApplicationContext ctx = new FileSystemXmlApplicationContext(CONTEXT_FILE); biz = (Biz) ctx.getBean("biz"); |
最好放開控制權(quán)。通常不必直接訪問應(yīng)用程序上下文。框架會執(zhí)行該操作。例如,如果您正在使用servlet,那么Spring框架會為每一個 servlet提供一個上下文,并為所有servlet提供一個總體上下文。通常可以從中獲得正確的上下文信息,隨后您就會看到這一點。既然已經(jīng)看到了表示jPetStore應(yīng)用程序的配置文件,現(xiàn)在應(yīng)該看看如何構(gòu)建各個元素:
域模型
與本書闡述的原理相對應(yīng),該應(yīng)用程序以圖8-3中的透明域模型為基礎(chǔ)。該域模型包含表示現(xiàn)實世界的各個對象之間的業(yè)務(wù)關(guān)系。Pet Store由包含項目的cart(購物車)和order(訂單)組成。

圖8-3 應(yīng)用程序的中心是域模型。
應(yīng)用程序表示了一個簡單的寵物商店。它由一個包含購物車項目(cart item)的購物車組成,該購物車又填充了一個包含線項目(line item)的訂單。項目(item)由按類別(category)組織的產(chǎn)品(product)組成。每個對象都是一個透明的業(yè)務(wù)對象,被實現(xiàn)為具有一些屬性和業(yè)務(wù)方法的Java bean。例8-2展示了一個CartItem。為了簡單起見,我已經(jīng)去掉導(dǎo)入和包細(xì)節(jié)。
例8-2CartItem.java
代碼: |
[1] public class CartItem implements Serializable { /*Private Fields*/ private Item item; private int quantity; private boolean inStock; /*JavaBeans Properties*/ [2] public boolean isInStock() { return inStock; } public void setInStock(boolean inStock) { this.inStock = inStock; } public Item getItem( ) { return item; } public void setItem(Item item) { this.item = item; } public int getQuantity( ) { return quantity; } public void setQuantity(int quantity) { this.quantity = quantity; } [3] public double getTotalPrice() { if (item != null) { return item.getListPrice( ) * quantity; } else { return 0; } } /*Public methods*/ public void incrementQuantity( ) { quantity++; } } |
以下是注釋的含義:
[1]Spring框架不會強(qiáng)迫組件繼承Spring類。它們是完全透明的,并且如果進(jìn)行測試或者情況需要,還可以駐留在容器的外部。
[2]每一個字段都使用get和set方法進(jìn)行包裝,以便Spring可以通過Java反射來配置他們。(Spring還可以通過構(gòu)造函數(shù)來配置它們。)
[3]與很多EJB應(yīng)用程序不同,在域模型中包含業(yè)務(wù)域邏輯非常有用。
我將這種模型稱作passive。它完全由域外面的對象調(diào)用,并且僅與域中的其他對象耦合。注意,雖然它具有私有屬性和公有字段,但是它不僅僅是一個值對象。它包含用于計算總價和增加數(shù)量的業(yè)務(wù)方法。這種設(shè)計使得該業(yè)務(wù)對象易于理解和重用,即使是在整體設(shè)計改進(jìn)的情況下。當(dāng)我們介紹持久性方面時,您就會看到該模型的其他部分。
下周,在這個摘錄自《Better, Faster, Lighter Java》一書的Spring系列的最后一部分中,作者將講述如何將持久性添加到Pet Store例子中,并討論Spring框架中的表示邏輯。
原文出處: Demonstrating Spring's Finesse http://www.onjava.com/pub/a/onjava/excerpt/BFLJava_chap8/index.html
作者簡介
Bruce A.ate是一名山地車手和皮劃艇手,也是2個孩子的父親。在閑暇時間里,他還是一名獨(dú)立顧問。他住在德克薩斯州的首府奧斯汀。他編寫了4本書,其中包括最暢銷的《Bitter Java》一書,最近出版了《Better,Faster,Lighter Java》(O'Reilly)。
Alexander Ananiev是一個程序員、作者、導(dǎo)師和指導(dǎo)員,他專攻現(xiàn)實世界軟件應(yīng)用程序。