1.收集的一些資料 “好的開始是成功的一半”,但凡一種新的技術(shù),開始階段一般是很苦惱的。為了不讓更多的人走同樣的彎路,我這里就把學(xué)習(xí)Spring的經(jīng)驗(yàn)與大家分享, 一起快樂一下。
Spring是什么?反正這里我不會談?wù)摯禾斓?。我要說的是Spring Framework ,它又是用來做什么的呢?一會半會我也說不清楚。還好現(xiàn)在是互聯(lián)網(wǎng)的時(shí)代,google一下,會發(fā)現(xiàn)不少有用的東西。
先來到Spring的大本營:http://www./ 可以看看 About Spring,最重要的是下載一個(gè)
Spring版本。
Spring的下載包有兩種,一種是帶有“with-dependencies”名稱的,這種包含了Spring常用到的第三方包,比如Hibernate、aopalliance、jakarta-commons等。這里就使用了這種包,可以省卻查找第三方包的麻煩。
當(dāng)前版本1.2.1 :spring-framework-1.2.1-with-dependencies.zip
解壓這個(gè)包,可以在 docs\reference目錄下找到Spring 的參考手冊,有html和pdf兩種格式。如果你的英文不太好,可以看看Spring中文論壇翻譯的1.1版本的中文版(pdf格式)。這個(gè)參考手冊就是入門的不二法寶。
● 新手剛學(xué)Spring時(shí),可能對一些概念似懂非懂,比如IoC(這里可不是國際奧委會)、DI等。這里向你推薦幾篇好文章,有助于理解Spring。
· Rod Johnson:Introduction to Spring Framework (Spring 1.2版本)
Java視線論壇上翻譯:Introducing to Spring Framework(中文修訂版 舊版本)
· Robert C Martin, Bob: The Dependency Inversion Principle
透明對此文的翻譯: IoC 容器和Dependency Injection 模式
· 冰云: 介紹 IOC
· 夏昕:Spring開發(fā)指南
· 良葛格:Spring入門(非常適合新手入門) · javaboutique網(wǎng)站上有篇教程(入門): The Spring Framework
● 如果要系統(tǒng)的學(xué)習(xí)Spring,還是需要Book的。
· Rod Johnson:Expert One-on-One J2EE Design and Development(10/2002)
看看作者是誰,就知道這本書的質(zhì)量如何了。毫無疑問,這本書吹響了向Spring進(jìn)軍的號角。前半部分主要闡述了J2EE開發(fā)的方方面面的經(jīng)驗(yàn)和設(shè)計(jì),后半部分通過對J2EE的改善設(shè)計(jì)而引申出了SpringFramework。這本書的中譯本也出來了,不過翻譯的一般。
· Rod Johnson, Juergen Hoeller: Expert One-on-One J2EE Development without EJB(7/2004)
看看書名就會嚇一跳,不過Rod Johnson完全有資格說出來。前半本介紹EJB的不足,后半本講Spring的原理。這本書的中譯本也出來了。
· Bruce A. Tate, Justin Gehtland:Better, Faster, Lighter Java(5/2004)
這本書主要闡述了如何利用Java進(jìn)行輕量級開發(fā),有關(guān)Spring的內(nèi)容比較少,只有一章,不過此書獲得了Jolt 大獎,質(zhì)量肯定沒的說了。
· Craig Walls, Ryan Breidenbach: Spring in Action(1/2005)
Manning出版的“in action”系列圖書,質(zhì)量一直非常好。此書系統(tǒng)介紹了Spring的方方面面,解析相當(dāng)清晰。
· Matt Raible: Spring Live
這本是source beat的電子書(只出電子版)。如果要深入這本書,需要有相當(dāng)?shù)幕A(chǔ)。這本書非常適合有實(shí)踐項(xiàng)目經(jīng)驗(yàn)的人。采用TDD的方式使用Spring,而且提供Spring整合其他framework的各種作法 (相當(dāng)多)。同時(shí)作者也維護(hù)著一個(gè)開源的項(xiàng)目appfuse。
· Rob Harrop,Jan Machacek:Pro Spring(1/2005)
我目前只看過了樣章,還很不錯(cuò),很系統(tǒng),也很細(xì)致,尤其書中提供的源代碼很適合新手練習(xí)。
· Rod Johnson等5人: Professional Java Development with the Spring Framework
預(yù)計(jì)2005年7月出版,作者陣容挺龐大的,幾乎都是Spring開發(fā)團(tuán)隊(duì)的,值得期待。
· 羅時(shí)飛 精通Spring
這好像是目前為止系統(tǒng)介紹Spring的唯一簡體中文書籍。
以上書籍都在網(wǎng)上提供了書中的源代碼下載和部分樣章,如果拿不到書,看看源代碼也是很不錯(cuò)。
● 說完書籍,再介紹一些好的論壇。
最后給大家推薦一個(gè)不錯(cuò)的資源收集站點(diǎn) http://www./
在其右上方的搜索欄中填入“spring”,可以獲得不少整理好的有關(guān)spring的資料。
好了,先寫到這里了,以后會陸續(xù)添加一些好的資料和站點(diǎn)。 2.HelloWorld(1)這篇文章主要談?wù)凷pring的入門開發(fā),例子很簡單,就是輸出一條語句。有關(guān)各種軟件的配置這里就不在多說了,如有不明白的,可以參考我以前的文章。 在開始看這篇文章之前,最好弄清楚IoC、DI等概念,參考《快速上手Spring--1.收集的一些資料》。
1. 所需軟件
· JDK 5.0
如果安裝后在Eclipse中看不到XmlBuddy,那么在eclipse命令后加上“-clean”參數(shù)。
2. 配置
● 配置Eclipse:
· Window->Perferences->Java->Compiler:將"Compiler compliance level"設(shè)為“5.0”
· Window->Perferences->Java->Build Path:勾選“Folders”
● 建立庫文件夾
具體做法參考《Eclipse快速上手Hibernate--1. 入門實(shí)例》一文中的“建立庫文件夾”的相關(guān)部分。
這里先將spring-framework-1.2.1-with-dependencies.zip解壓,將其中的spring.jar(dist目錄中)、commons-logging.jar(lib\jakarta-commons目錄)、log4j-1.2.9.jar(lib\log4j目錄)這三個(gè)文件復(fù)制到的”D:\java\Spring\lib" 目錄中,然后在Eclipse中建立一個(gè)“Spring”庫,將那三個(gè)文件添加進(jìn)“Spring”庫中。
![]() 1. 創(chuàng)建項(xiàng)目
· 新建一個(gè)Java Project:SpringHello,注意要導(dǎo)入用戶庫Spring。
· 這是完成后整個(gè)項(xiàng)目的結(jié)構(gòu)(預(yù)覽一下):
![]() · 項(xiàng)目源碼下載(不包含庫文件):http://free./?javamxj Spring目錄下面。
2. 簡單的HelloWorld
·下面開始創(chuàng)建一個(gè)新類:HelloWorld ;包名:javamxj.spring.beginning1,代碼如下:
OK!非常簡單,我就是要它打印出一條語句“Hello World!”。
現(xiàn)在我不想輸出“Hello World!”,我想隨心所欲的輸出任何語句,很簡單啊!將“Hello World!”替換成所希望輸出的語句即可。不過這樣有一個(gè)缺點(diǎn),每次修改好了,都需要重新編譯一下程序。像這樣的小程序固然無所謂,可是如果是一個(gè)大項(xiàng)目,這樣做就有些討厭了。
還好,只要稍微修改一下程序,通過參數(shù)輸入即可。
· 繼續(xù)在這個(gè)包下建立一個(gè)新類:HelloWorldWithCommandLine,同樣非常簡單:
· 選中HelloWorldWithCommandLine,右擊->Run As->Run...,在彈出窗口切換到“Arguments”欄,在“program arguments”中填入“Hello,javamxj!”,如下圖:
![]() 這樣,就輸出了我希望的語句。
第一部分到此,請繼續(xù)看第二部分。
2.HelloWorld(2)這是第二部分。
3. 采用“工廠模式”
· 新建一個(gè)包,包名:javamxj.spring.beginning2,在這個(gè)包下,新建一個(gè)“Hello”接口,這個(gè)接口含有一個(gè)方法。
· 分別新建兩個(gè)類,實(shí)現(xiàn)這個(gè)接口。
· 建立一個(gè)工廠類,調(diào)用上面兩個(gè)實(shí)現(xiàn)接口的子類。
· 最后,利用工廠類,測試一下。
運(yùn)行Test,控制臺輸出如下語句:
Hello World!
Hello, javamxj! 4. Setter Injection
講了這么多,似乎一點(diǎn)都不關(guān)Spring的事,別急,下面就看看用Spring是如何實(shí)現(xiàn)的。
· 新建一個(gè)包,包名:javamxj.spring.beginning3
· 在這個(gè)包下,新建一個(gè)HelloBean的類,這個(gè)類有一個(gè)屬性:helloWorld屬性,這個(gè)屬性只是一個(gè)字符串??梢酝ㄟ^setHelloWorld方法設(shè)置這個(gè)屬性,getHelloWorld方法得到這個(gè)屬性。
· 同樣,在這個(gè)包下,建立一個(gè)XML文件,它是Spring配置文件。
Spring配置文件必須遵循spring-beans.dtd定義的內(nèi)容模型。
這個(gè)XML文件在Spring容器中聲明了一個(gè)HelloBean的實(shí)例,并且將它的helloWorld屬性設(shè)置為“Hello! Javamxj!”。
分析這個(gè)XML文件,位于根部的是
在
bean.xml必須在您的CLASSPATH可以存取到的目錄中。
· 新建Main.java,測試一下。
這里使用的BeanFactory類就是Spring容器。在將hello.xml文件裝入容器后,main方法調(diào)用BeanFactory的getBean方法檢索出了helloBean服務(wù)的一個(gè)引用。通過這個(gè)引用,它調(diào)用了getHelloWorld方法。當(dāng)我們運(yùn)行這個(gè)Hello應(yīng)用時(shí),它會打印出“Hello! Javamxj!”。
· 另外,為了更好的調(diào)試程序,了解運(yùn)行機(jī)理,建立一個(gè)log4j.properties,放在src目錄下。
5. Constructor Injection
· 新建一個(gè)包,包名:javamxj.spring.beginning3
· 新建一個(gè)HelloBean.java文件,可以與Setter Injection中的HelloBean比較一下,注意是通過Constructor設(shè)置helloWorld屬性值的。
· 同樣,在這個(gè)包下,也需要一個(gè)Spring配置文件。
這里通過
· 測試一下。
這樣,通過BeanFactory的getBean方法,以及xml配置文件,避免了在Main類中直接實(shí)例化HelloBean,消除了應(yīng)用程序(Main)與服務(wù)(HelloBean)之間的耦合,實(shí)現(xiàn)了IOC(控制反轉(zhuǎn))或者說實(shí)現(xiàn)了依賴的注射(Dependency Injection)。
Setter Injection和Constructor Injection都有自己的長處和不足。至于,是選擇Setter Injection,還是選擇Constructor Injection?在《Spring in Action》、《Inversion of Control Containers and the Dependency Injection pattern》和《Spring開發(fā)指南》都有比較詳細(xì)的論述,這里就不多說了。 3. 加載Bean的配置文件1. 創(chuàng)建項(xiàng)目
· 新建一個(gè)Java Project:SpringBeanFile,注意要導(dǎo)入用戶庫Spring。
· 這是完成后整個(gè)項(xiàng)目的結(jié)構(gòu)(預(yù)覽一下):
![]() · 項(xiàng)目源碼下載(不包含庫文件):http://free./?javamxj Spring目錄下面。
2. 編寫類文件
· 下面開始創(chuàng)建一個(gè)新類:BeanFile ;包名:javamxj.spring.beanfile
· 新建Test.java,測試一下。
Test.java package javamxj.spring.beanfile; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.InputStream; import org.springframework.beans.factory.BeanFactory; import org.springframework.beans.factory.support.BeanDefinitionRegistry; import org.springframework.beans.factory.support.DefaultListableBeanFactory; import org.springframework.beans.factory.support.PropertiesBeanDefinitionReader; import org.springframework.beans.factory.xml.XmlBeanFactory; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import org.springframework.core.io.ClassPathResource; import org.springframework.core.io.FileSystemResource; import org.springframework.core.io.InputStreamResource; import org.springframework.core.io.Resource; public class Test { public static void main(String[] args) { // 直接調(diào)用HelloBean BeanFile bf = new BeanFile(); System.out.println(bf.getBeanFile()); /** * 利用XmlBeanFactory(Resource resource) * 這里Resource必須是xml格式 * Resource包括:AbstractResource, ClassPathResource, FileSystemResource, * InputStreamResource, ServletContextResource, UrlResource */ /* * 利用 InputStreamResource(InputStream inputStream) * 要將bean.xml放在項(xiàng)目根目錄下 */ InputStream is = null; try { is = new FileInputStream("bean1.xml"); } catch (FileNotFoundException e) { e.printStackTrace(); } Resource resource = new InputStreamResource(is); sayHello(resource); /* * 利用 ClassPathResource(String path) * 要將bean.xml放在源文件夾(src)目錄下 */ resource = new ClassPathResource("bean2.xml"); sayHello(resource); /* * 利用 FileSystemResource(String path) * 要將bean.xml放在項(xiàng)目根目錄下 */ resource = new FileSystemResource("bean3.xml"); sayHello(resource); /* * 利用 Properties * 要將bean.properties放在類路徑--源文件夾(src)目錄下 */ BeanDefinitionRegistry reg = new DefaultListableBeanFactory(); PropertiesBeanDefinitionReader reader = new PropertiesBeanDefinitionReader( reg); reader.loadBeanDefinitions(new ClassPathResource("bean.properties")); BeanFactory factory = (BeanFactory) reg; bf = (BeanFile) factory.getBean("beanFile"); System.out.println("利用 " + bf.getBeanFile() + " 加載 Bean.properties"); /* * 利用 ApplicationContext * 要將bean.xml放在類路徑--源文件夾(src)目錄下 */ ApplicationContext appContext = new ClassPathXmlApplicationContext( "bean4.xml"); bf = (BeanFile) appContext.getBean("beanFile"); System.out.println("利用 " + bf.getBeanFile() + " 加載 Bean.xml"); } public static void sayHello(Resource resource) { BeanFactory factory = new XmlBeanFactory(resource); BeanFile bf = (BeanFile) factory.getBean("beanFile"); System.out.println("利用 " + bf.getBeanFile() + " 加載 Bean.xml"); } } 3. 配置文件
由上面的Test.java可知,這里一共需要四個(gè)XML文件和一個(gè)Properties文件,現(xiàn)在分別建立。
· bean1.xml放在項(xiàng)目根目錄下:
bean2.xml、bean3.xml、bean4.xml與bean1.xml相似,僅僅需要替換一下
· bean2.xml放在源文件夾(src)目錄下:
· bean3.xml放在項(xiàng)目根目錄下:
· bean4.xml放在源文件夾(src)目錄下:
Spring也可以使用屬性文件來定義配置文件,如下: · bean.properties放在源文件夾(src)目錄下:
· 還需要將上文《快速上手Spring--2.HelloWorld(2)》中的log4j.properties復(fù)制到src目錄下。
4. 運(yùn)行程序
右擊Test.java,運(yùn)行程序,控制臺輸出如下:
多種方式加載Bean的配置文件
利用 InputStreamResource(InputStream inputStream) 加載 Bean.xml 利用 ClassPathResource(String path) 加載 Bean.xml 利用 FileSystemResource(String path) 加載 Bean.xml 利用 properties 加載 Bean.properties 利用 ApplicationContext 加載 Bean.xml 5. 小結(jié)
這篇文章主要談?wù)摿巳绾渭虞dSpring的配置文件,一般來說,就是BeanFactory和ApplicationContext。最常使用的、簡單的BeanFactory實(shí)現(xiàn)是org.springframework.beans.factory.xml.XmlBeanFactory,其加載方式為:
BeanFactory factory = new XmlBeanFactory(Resource resource)
這里resource必須是xml格式。Resource包括: AbstractResource, ClassPathResource, FileSystemResource, InputStreamResource, ServletContextResource, UrlResource。這篇文章 談了常用的三種:ClassPathResource, FileSystemResource, InputStreamResource。
ApplicationContext包括了BeanFactory的所有功能,也要比BeanFactory強(qiáng)大的多(以后會詳細(xì)介紹的)。這里只簡單的使用了ClassPathXmlApplicationContext加載了Bean配置文件。你可以將log4j.properties中的“Warn”改為“Debug”, 對比一下和ClassPathResource的輸出, 在Eclipse中,bean2.xml、bean4xml雖然都是放在源文件夾(src)目錄下,但實(shí)際上,是由已經(jīng)編譯好的Test.class從類文件夾(這里是bin文件夾)中加載的。 4.安裝和使用SpringIDE 這篇文章談?wù)勅绾伟惭b與使用SpringIDE。作為輔助Spring開發(fā)的工具,SpringIDE還是比較有用的。
● 軟件配置:
· Eclipse 3.1
· SpringIDE
當(dāng)前版本:1.2.1 http:///updatesite/updatesite_1.2.1.zip
· GEF :只需要GEF Runtime就行了,3.1版本的下載地址。
● 安裝:
· 解壓安裝GEF3.1,
· 在eclipe中打開 Help ->Software Updates ->Find and install,選擇
Search for new features to install. 在打開的界面中,選擇new archived site,選擇下載的zip文件(如果沒有下載這個(gè)zip文件,也可以選擇New Remote Site,直接從網(wǎng)上更新),再選擇一個(gè)安裝的目錄就可以了. ![]() 點(diǎn)擊Next,在出現(xiàn)的對話框中勾選“updatesite_1.2.1.zip”,然后一直點(diǎn)擊Next,直到安裝完成。
· 如果有疑問,可以參考http:///project/wiki/SpringideInstall
● 使用:
這里以前面文章中的SpringHello項(xiàng)目實(shí)踐一下如何使用SpringIDE。
· 右擊SpringHello,在彈出菜單中選擇“Add Spring Project Nature”,如下圖:
![]() 如果成功,則這時(shí)該項(xiàng)目就會在右上角掛上了“S”.
· 右鍵項(xiàng)目名,查看其properties,選擇“Spring Beans”,切換到“Config Files”,點(diǎn)擊“Add”,將包javamxj.spring.beginning3下的bean.xml加入到其中。
![]() · 這時(shí)可以看到bean.xml和HelloBean.java的右上角都掛上了“S”。
![]() 這是由于SpringIDE分析加載的bean.xml文件,找到了“helloBean”指向的類HelloBean.java。如果找不到這個(gè)文件,則會顯示一個(gè)錯(cuò)誤,指明這個(gè)類找不到;如果將“helloBean”指向了包javamxj.spring.beginning4下的bean.xml,雖然這個(gè)類存在,但由于屬性不匹配,同樣會顯示出錯(cuò)誤。這樣就驗(yàn)證了XML的配置,可以提前知道配置中的錯(cuò)誤。
· Spring Beans view
選中bean.xml,切換到“Navigate” ,如圖:
![]() · 顯示圖表,如圖:
![]() 5.Bean的標(biāo)志符(id與name)又重新學(xué)習(xí)了Spring,想把自己的心得寫下來,感覺有些無從下手。想來想去,還是根據(jù)Spring中文論壇翻譯的《Spring Framework 開發(fā)參考手冊》(1.1版本的中文版,pdf格式),來組織自己的思路。在這個(gè)階段,我發(fā)布的關(guān)于Spring的文章,基本上都是入門級別的。相對而言,對于新手的幫助應(yīng)該會更大。 雖然當(dāng)前Spring的版本已經(jīng)是1.2.2了,但同1.1版本的中文版相比,spring-reference還是相差不大的(尤其是前面幾章的基礎(chǔ)部分),所以采用的還是1.1版本的開發(fā)參考手冊。
這個(gè)系列的文章,我準(zhǔn)備根據(jù)開發(fā)參考手冊的講解,有針對性的增加大量的比較簡單的實(shí)例,每個(gè)實(shí)例盡量只解釋一個(gè)問題。下面就從3.2.4小節(jié)——《Bean的標(biāo)志符(id與name)》講起。
相關(guān)軟件的配置可以參考《快速上手Spring--2.HelloWorld(1)》。
一般來說,在一個(gè)XmlBeanFactory中,定義一個(gè)bean時(shí),采用的是
這里id的命名格式必須符合XML ID屬性的命名規(guī)范,例如,不能以數(shù)字開頭,“222”就不是合法的id值。為了解決這個(gè)問題,可以使用name屬性指定一個(gè)和多個(gè)id(用逗號或者分號隔離)。 這里還是以HelloBean為例,這三個(gè)文件都放在包javamxj.spring.basic.aliases下。
· HelloBean
· 配置文件
在這個(gè)Bean中,除了id屬性,還含有name屬性,其值為“2hello”、“javamxj@yahoo.com.cn”,因?yàn)橐詳?shù)字開頭、含有特殊字符“@”,它們是不能用在id屬性中的。
· 測試程序:
可以看出,使用中id屬性和name屬性幾乎沒有任何區(qū)別。
調(diào)用BeanFactory.getAliases(String)的方法時(shí),傳入的參數(shù)可以是任意一個(gè)Bean名字,輸出的別名則是除去id之外的所有Bean名,如果沒有指定id,則將其name屬性中的第一個(gè)值指定為id。 當(dāng)然,Bean的name屬性不僅僅只是為了輸入id屬性所不允許的名字,它還有其它的用處,在后面的文章中會提及的。
6. Singleton的使用與否上篇文章已經(jīng)談了《Spring Framework 開發(fā)參考手冊》的3.2.4小節(jié)——《Bean的標(biāo)志符(id與name)》,現(xiàn)在繼續(xù)3.2.5小節(jié)——《Singleton的使用與否》。 文檔已經(jīng)把Singleton說的很清楚了,這里也不廢話了。主要是了解在Spring中,默認(rèn)的部署方式是Singleton,沒有特別需要的話,一般使用Singleton。
相關(guān)軟件的配置可以參考《快速上手Spring--2.HelloWorld(1)》。
這里還是以HelloBean為例,這三個(gè)文件都放在包javamxj.spring.basic.singleton下。
· HelloBean
這里多加了屬性i,用它得到隨機(jī)數(shù)。
· 配置文件
在這個(gè)Beans中,定義了兩個(gè)bean,都指向HelloBean類,主要不同就是第二個(gè)bean指明了singleton="false",即不采用singleton部署方式。
· 測試程序:
分別取得singletonBean和prototypeBean各兩個(gè)實(shí)例,然后輸出隨機(jī)數(shù),最后比較同一個(gè)bean的兩個(gè)實(shí)例的引用是否相同。
·運(yùn)行,控制臺輸出:
Hello! 這是singletonBean!
輸出隨機(jī)整數(shù): 7 Hello! 這是singletonBean! 輸出隨機(jī)整數(shù): 7 h1==h2: true Hello! 這是prototypeBean!
輸出隨機(jī)整數(shù): 95 Hello! 這是prototypeBean! 輸出隨機(jī)整數(shù): 60 h3==h4: false ·這篇文章和上篇文章的源代碼下載(不包含庫文件):http://free./?javamxj Spring目錄下面的SpringBasic.zip。
|
|