Spring框架教程全書ppt課件匯總(完整版)_第1頁(yè)
Spring框架教程全書ppt課件匯總(完整版)_第2頁(yè)
Spring框架教程全書ppt課件匯總(完整版)_第3頁(yè)
Spring框架教程全書ppt課件匯總(完整版)_第4頁(yè)
Spring框架教程全書ppt課件匯總(完整版)_第5頁(yè)
已閱讀5頁(yè),還剩511頁(yè)未讀 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡(jiǎn)介

1、1.1Spring簡(jiǎn)介1.2IoC容器1.3 Spring IoC容器1.1Spring簡(jiǎn)介Spring是一個(gè)開源框架,它由Rod Johnson創(chuàng)建。Spring誕生之初是為了解決企業(yè)應(yīng)用軟件開發(fā)日益復(fù)雜的難題。Spring創(chuàng)建的初衷如下:(1) J2EE應(yīng)該更加簡(jiǎn)單。(2) 使用接口而不是使用類,是更好的編程習(xí)慣。(3) 為JavaBean提供了一個(gè)更好的應(yīng)用配置框架。(4) 更多地強(qiáng)調(diào)面向?qū)ο蟮脑O(shè)計(jì),而不是現(xiàn)行的技術(shù)。(5) 盡量減少不必要的異常捕捉。(6) 使應(yīng)用程序更加容易測(cè)試。Spring框架目標(biāo):(1) 可以令人方便愉快地使用Spring。(2) 應(yīng)用程序代碼并不依賴于Sprin

2、g API。(3) Spring不是和現(xiàn)有的解決方案競(jìng)爭(zhēng),而是致力于與現(xiàn)有解決方案融合在一起。1.1.1 Spring歷史Spring自從2003年發(fā)布以來,一直是Java開源框架的奇跡之一。Spring從2004年3月到現(xiàn)在,已經(jīng)發(fā)布了1.0、1.1、1.2、2.0、2.5、3.0、4.0等幾個(gè)主要版本,目前發(fā)布的版本增加了許多特性,比如Spring表達(dá)式語言、IoC增強(qiáng)、聲明模型驗(yàn)證、更多的注解支持和嵌入式數(shù)據(jù)庫(kù)支持等。1.1.2Spring項(xiàng)目簡(jiǎn)介圍繞著Spring框架本身,有許多優(yōu)秀的項(xiàng)目,此處只對(duì)Spring的常用項(xiàng)目進(jìn)行簡(jiǎn)單介紹。(1) Spring Framework(Core)

3、:整個(gè)Spring項(xiàng)目的核心。(2) Spring Web Flow:定義了一種特定的語言來描述工作流,且其高級(jí)的工作流控制器引擎可以管理會(huì)話狀態(tài),支持AJAX來構(gòu)建豐富的客戶端體驗(yàn),還能對(duì)JSF提供支持。(3) Spring Security:廣泛使用的基于Spring的認(rèn)證和安全工具。(4) Spring Dynamic Modules:可以讓Spring應(yīng)用運(yùn)行在OSGi平臺(tái)上。(5) Spring Batch:提供構(gòu)建批處理應(yīng)用和自動(dòng)化操作的框架。(6) Spring Android:為Android終端開發(fā)應(yīng)用提供Spring支持,并提供了一個(gè)基于Jave的在Android應(yīng)用環(huán)境中

4、工作的REST客戶端。(7) Spring Mobile:是基于Spring MVC構(gòu)建的,可為移動(dòng)終端的服務(wù)器應(yīng)用開發(fā)提供支持。(8) Spring Social:Spring框架的擴(kuò)展,可以幫助Spring應(yīng)用更方便地使用SNS(Social Network Service)。所有基于Spring的項(xiàng)目都是以Spring Framework為基礎(chǔ)開發(fā)出來的。事實(shí)上,Spring Framework也是Spring體系的核心。作為平臺(tái),Spring將許多應(yīng)用開發(fā)中遇到的共性問題進(jìn)行了抽象;同時(shí),作為一個(gè)輕量級(jí)的應(yīng)用開發(fā)框架,Spring和傳統(tǒng)的J2EE開發(fā)相比,有其自身特點(diǎn)。通過這些自身特點(diǎn)

5、,Spring充分體現(xiàn)了它的設(shè)計(jì)理念:支持POJO和使用JavaBean的開發(fā)方式、面向接口開發(fā)、支持OO(面向?qū)ο?的設(shè)計(jì)方法。到目前為止,Spring Framework一共包含大約20個(gè)模塊,這些模塊大多集中在Core Container、Data Access/Integration、Web、AOP、Instrumentation和Test部分。圖1-1描述了Spring Framework模塊的結(jié)構(gòu)。以下是部分Spring Framework模塊的具體作用。1. Core ContainerCore Container部分主要包含Beans、Core、Context和Expressi

6、on Language等模塊。(1) Beans和Core模塊:框架的基礎(chǔ)部分,提供依賴注入和IoC(控制反轉(zhuǎn))特性。(2) Context模塊:構(gòu)建于Beans和Core模塊基礎(chǔ)之上,提供了一種類似于JNDI注冊(cè)器的框架式對(duì)象訪問方法。(3) Expression Language模塊:提供了一個(gè)強(qiáng)大的表達(dá)式語言,可以在運(yùn)行時(shí)查詢和操縱對(duì)象。2. Data Access/IntegrationData Access/Integration部分包含JDBC、ORM、OXM、JMS和Transaction等模塊。(1) JDBC模塊:提供了一個(gè)JDBC抽象層,可以消除冗長(zhǎng)的JDBC編碼和解析數(shù)據(jù)

7、庫(kù)廠商特有的錯(cuò)誤代碼。(2) ORM模塊:為流行的對(duì)象/關(guān)系映射APIJPA、JDO、Hibernate、iBatis等提供了一個(gè)交互層。(3) OXM模塊:提供了一個(gè)對(duì)Object/XML映射實(shí)現(xiàn)的抽象層。(4) JMS(Java Messaging Service)模塊:主要包含制造和消費(fèi)消息的特性。(5) Transaction模塊:支持編程和聲明性的事務(wù)管理,這些事務(wù)類必須實(shí)現(xiàn)特定的接口,并且對(duì)所有的POJO都適用。3. WebWeb部分包含Web、Servlet、Struts、Porlet等模塊。(1) Web模塊:提供了基礎(chǔ)的面向Web的集成特性,它還包含Spring遠(yuǎn)程支持中的W

8、eb相關(guān)部分。(2) Servlet模塊:包含Spring的Model-View-Controller(MVC)實(shí)現(xiàn)。(3) Struts模塊:提供了對(duì)Struts的支持,使得類在Spring應(yīng)用中能夠與一個(gè)典型的Struts Web層集成在一起。(4) Portlet模塊:提供了用于Portlet環(huán)境和Web-Servlet模塊的MVC實(shí)現(xiàn)。4. AOPAOP即面向切面編程。在程序開發(fā)中AOP可以解決一些系統(tǒng)層面的問題。5. Instrumentation和TestInstrumentation模塊提供了Class Instrumentation支持和ClassLoader實(shí)現(xiàn),可以在某些特

9、定的應(yīng)用服務(wù)器上使用。Test模塊支持使用JUnit和TestNG對(duì)Spring組件進(jìn)行測(cè)試。1.1.3 Spring Framework安裝本節(jié)使用的是Spring Framework 3.1.3,以Spring Framework 3.1.3為例,該文件壓縮包中含有開發(fā)必需的jar包、源代碼和幫助文檔。解壓包圖如圖1-2所示,圖中各文件夾說明如下:dist:存放Spring Framework各功能模塊的jar包。docs:存放幫助文檔和Spring Framework的API參考。projects:按功能存放Spring Framework各模塊的項(xiàng)目源代碼,包含Eclipse項(xiàng)目文件和

10、Maven項(xiàng)目構(gòu)建配置文件。src:打包按功能存放的Spring Framework各模塊的項(xiàng)目源代碼,只含有源碼,不含項(xiàng)目配置文件。在創(chuàng)建Java項(xiàng)目后,如果需要使用Spring Framework,則要根據(jù)需要導(dǎo)入dist目錄下面相關(guān)的jar包。為了方便項(xiàng)目的管理,可以使用Eclipse自定義庫(kù),把Spring Framework的相關(guān)文件放到用戶自定義庫(kù)中,當(dāng)創(chuàng)建項(xiàng)目時(shí)可直接使用該庫(kù)。創(chuàng)建自定義庫(kù)的方式如圖1-3所示,在Eclipse菜單中選擇WindowPreferencesJavaBuild PathUser Libraries,然后點(diǎn)擊“New”新建用戶自定義庫(kù),新建完畢后,選擇“

11、Add JARs”添加上述所有的jar包,再選擇“OK”,即可完成用戶自定義庫(kù)的創(chuàng)建。完成用戶自定義庫(kù)的創(chuàng)建后,當(dāng)創(chuàng)建Java項(xiàng)目時(shí),可以在創(chuàng)建的配置向?qū)е袑?dǎo)入用戶自定義庫(kù),如圖1-4所示。配置好Spring開發(fā)環(huán)境后就可以使用Spring框架進(jìn)行開發(fā)了。本章從Spring Framework的核心IoC容器開始介紹。1.2IoC容器1.2.1IoC容器和依賴倒置原則IoC(Inverse of Control,控制反轉(zhuǎn))是Spring容器的核心,其他模塊都是在此基礎(chǔ)上發(fā)展起來的。依賴倒置原則(Dependency Inversion Principle,DIP)是面向?qū)ο笤O(shè)計(jì)領(lǐng)域的一種軟件設(shè)

12、計(jì)原則。依賴倒置原則基于這樣一個(gè)事實(shí):相對(duì)于細(xì)節(jié)的多變性,抽象的東西要穩(wěn)定得多。即,以抽象為基礎(chǔ)搭建起來的架構(gòu)比以細(xì)節(jié)為基礎(chǔ)搭建起來的架構(gòu)要穩(wěn)定得多。在Java中,抽象指的是接口或者抽象類,細(xì)節(jié)就是具體的實(shí)現(xiàn)類,使用接口或者抽象類的目的是制定好規(guī)范和契約,而不去涉及任何具體的操作,把展現(xiàn)細(xì)節(jié)的任務(wù)交給實(shí)現(xiàn)類去完成。依賴倒置原則的核心思想是面向接口編程,使用接口是實(shí)現(xiàn)解耦合的最重要的途徑,此處用一個(gè)例子來說明面向接口編程比面向?qū)崿F(xiàn)編程好的原因。假設(shè)現(xiàn)在有一臺(tái)電腦需要安裝打印機(jī),但目前只有一種類型的打印機(jī)可選,即黑白打印機(jī)。首先,設(shè)計(jì)打印機(jī)類:public class GrayPrinter /初

13、始化方法 public void init() System.out.println(啟動(dòng)打印機(jī)!); /打印 public void print(String txt) System.out.println(打印黑白文字:.concat(txt); 此處,設(shè)計(jì)打印機(jī)類有兩個(gè)方法,一個(gè)是init啟動(dòng),另一個(gè)是print打印方法。其次,設(shè)計(jì)電腦類:public class Computer GrayPrinter p; public GrayPrinter getP() return p; public void setP(GrayPrinter p) this.p = p; / 打印文本 pu

14、blic void printTxt(String txt) p.init(); p.print(txt); 在電腦類中有一個(gè)打印機(jī)屬性和一個(gè)打印方法。最后,為測(cè)試類代碼:public class TestComputer /* * param args */ public static void main(String args) / TODO Auto-generated method stub /創(chuàng)建電腦 Computer pc1 = new Computer(); /創(chuàng)建打印機(jī) GrayPrinter p = new GrayPrinter(); pc1.setP(p); /打印文本

15、pc1.getP().print(打印測(cè)試頁(yè).); 運(yùn)行測(cè)試代碼,得到需要的打印結(jié)果。過了幾年,人們發(fā)現(xiàn)這個(gè)世界還是彩色的比較好看,于是發(fā)明了彩色打印機(jī),此時(shí)打印機(jī)的選擇就變多了,為了實(shí)現(xiàn)彩色打印不得不多寫一個(gè)彩色打印機(jī)類,并修改電腦類。又過了幾年,人們發(fā)現(xiàn)激光打印機(jī)更清晰,于是,又需要修改電腦類總之,每次有新的打印機(jī)上市,就需要修改電腦類的代碼。事實(shí)上這是一個(gè)典型的依賴具體實(shí)現(xiàn)的例子電腦類對(duì)GrayPrinter產(chǎn)生了依賴,一旦有新型的打印機(jī)產(chǎn)生(即產(chǎn)生新的ColorPrinter、LazerPrinter等),就需要修改電腦類代碼。根據(jù)依賴倒置原則描述的,調(diào)用者應(yīng)該依賴被調(diào)用者的抽象,而不

16、是依賴于它的具體實(shí)現(xiàn),此時(shí)可以抽象出一個(gè)Printer接口,其他的具體實(shí)現(xiàn)類都靠這個(gè)接口實(shí)現(xiàn),這樣修改后,無論以后怎樣擴(kuò)展Printer類,都不需要再修改電腦類了。修改之后的代碼如下。Printer接口:public interface Printer /初始化方法 void init(); /打印 void print(String txt);GrayPrinter黑白打印機(jī):public class GrayPrinter implements Printer /初始化方法 Override public void init() System.out.println(啟動(dòng)打印機(jī)!); /打

17、印 Override public void print(String txt) System.out.println(打印黑白文字:.concat(txt); ColorPrinter彩色打印機(jī):public class ColorPrinter implements Printer /初始化方法 Override public void init() System.out.println(啟動(dòng)彩色打印機(jī)!); /打印 Override public void print(String txt) System.out.println(打印彩色文字:.concat(txt); 電腦類:publ

18、ic class Computer Printer p; / 打印文本 public void printTxt(String txt) p.init(); p.print(txt); public Printer getP() return p; public void setP(Printer p) this.p = p; 此時(shí)電腦類依賴的是Printer這個(gè)抽象接口,而不是依賴于Printer的具體實(shí)現(xiàn)。但在測(cè)試類中又存在相似的問題,比如現(xiàn)在需要彩色打印機(jī),具體代碼如下:public class TestComputer /* * param args */ public static

19、void main(String args) / TODO Auto-generated method stub /創(chuàng)建電腦 Computer pc1 = new Computer(); /創(chuàng)建打印機(jī) Printer p = new ColorPrinter(); pc1.setP(p); /打印文本 pc1.getP().print(打印測(cè)試頁(yè).); 在上述TestComputer測(cè)試類中,使用了new ColorPrinter方式創(chuàng)建Printer實(shí)例,假設(shè)把所有彩色打印機(jī)換成黑白的,則要修改TestComputer測(cè)試類中的代碼。為了減少修改代碼的次數(shù),可以寫一個(gè)配置文件,配置具體需要實(shí)

20、例化的類,然后在TestComputer測(cè)試類中讀取配置文件,再根據(jù)配置產(chǎn)生不同的實(shí)例。此時(shí)TestComputer測(cè)試類的改變?nèi)缦拢簆ublic class TestComputer private static Properties p = new Properties(); /讀取Bean配置文件 static try p.load(TestComputer.class.getResourceAsStream(/perties); catch (IOException e) System.out.println(無法找到配置文件!); /根據(jù)屬性文件中定義的關(guān)鍵字創(chuàng)建實(shí)例 public

21、static Object getBean(String keyName) Object o = null; try o = Class.forName(p.get(keyName).toString().newInstance(); catch (Exception e) System.out.println(無法實(shí)例化對(duì)象!); return o; /* * param args */ public static void main(String args) / TODO Auto-generated method stub /創(chuàng)建電腦 Computer pc1 = new Compute

22、r(); /創(chuàng)建打印機(jī) Printer p = (Printer)TestComputer.getBean(printer); pc1.setP(p); /打印文本 pc1.getP().print(打印測(cè)試頁(yè).); 可以看到,上述TestComputer測(cè)試類代碼在靜態(tài)塊中讀取了perties配置文件,同時(shí)提供了一個(gè)getBean方法,該方法可以根據(jù)perties的配置來實(shí)例化一個(gè)類,在給電腦裝配打印機(jī)的時(shí)候,不再采用new的方式直接實(shí)例化對(duì)象,而是通過調(diào)用getBean的方式獲取一個(gè)根據(jù)業(yè)務(wù)需要產(chǎn)生的具體實(shí)例。perties的代碼如下:printer=com.ssoft.ssh.demo2

23、.ColorPrinter#com.ssoft.ssh.demo2.GrayPrinter這里perties定義了一個(gè)名叫printer的主鍵,值是ColorPrinter類的全名,當(dāng)然,也可以根據(jù)具體的需要切換成GrayPrinter類。如此配置之后即可根據(jù)具體的業(yè)務(wù)需要產(chǎn)生不同的、和業(yè)務(wù)相關(guān)的Printer實(shí)例給TestComputer測(cè)試類使用,即便以后有了新類型的Printer,也不需要修改TestComputer測(cè)試類,只需要添加一個(gè)Printer的實(shí)現(xiàn)類,這樣,可以讓應(yīng)用程序具有很好的擴(kuò)展能力。需要注意的是,運(yùn)用很多設(shè)計(jì)模式或者類設(shè)計(jì)原則的時(shí)候并不會(huì)減少代碼量,相反會(huì)增加一定量的代

24、碼,但這樣做的好處是增強(qiáng)程序的擴(kuò)展能力,提高程序的維護(hù)性。在理解了上述例子之后,此時(shí)再講Spring的IoC容器就比較容易理解了。容器是用來裝東西的,Spring的IoC容器就是用來裝Bean實(shí)例的,然后把這些實(shí)例通過配置的方式注入調(diào)用者中,而不是直接在代碼中硬編碼實(shí)例對(duì)象,所以,IoC也叫作DI依賴注入(Dependency Injection)。1.2.2 依賴注入類型依賴注入通常分為三類,分別是接口注入(Type1型)、構(gòu)造器注入(Type2型)和setter注入(Type3型),其中Type2型和Type3型是比較常用的類型,尤其Type3型是使用最多的注入方式。所謂setter注入,

25、就是指調(diào)用者類提供一個(gè)setter方法,把被調(diào)用者作為參數(shù)傳遞給調(diào)用者,比如前面的電腦類代碼中有一個(gè)Printer屬性,我們通過setPrinter的方法把Printer對(duì)象的實(shí)例傳遞給它,這就是典型的setter注入方式。構(gòu)造器注入方式,表示的是調(diào)用者在實(shí)例化的時(shí)候必須注入被調(diào)用者的實(shí)例。若把上例改成構(gòu)造器注入,則電腦類代碼就必須改成如下方式:public class Computer Printer p; public Computer(Printer p) this.p = p; 在創(chuàng)建電腦類實(shí)例的時(shí)候,必須把Printer的實(shí)例注入給Computer實(shí)例:Computer c = ne

26、w Computer(new ColorPrinter();若把上例改成接口注入的方式,則電腦類必須實(shí)現(xiàn)一個(gè)接口,其代碼如下:public interface Computeable /定義接口注入 void inject(Printer p);public class Computer implements Computeable Printer p; public void inject(Printer p) this.p = p; 其中,調(diào)用代碼如下:Computeable pc = new Computer();pc.inject(new ColorPrinter);這種接口注入的方式

27、需要調(diào)用者必須實(shí)現(xiàn)一個(gè)指定的接口,典型的應(yīng)用有EJB(這種方式使用比較少,一般不推薦)。Spring IoC容器提供了Type2和Type3型的注入方式。1.3 Spring IoC容器1.3.1 BeanFactory容器BeanFactory采用工廠模式,提供了最基本的IoC容器功能:實(shí)例化對(duì)象、配置對(duì)象之間的依賴關(guān)系。在Spring中,所有的對(duì)象都是由BeanFactory工廠來生產(chǎn)管理的。BeanFactory只是一個(gè)接口類,它定義了IoC容器的一個(gè)標(biāo)準(zhǔn),卻沒有給出容器的具體實(shí)現(xiàn),因此還需要依靠具體的實(shí)現(xiàn)類。通俗地講,BeanFactory如同生活中定義的容器,而瓶子、罐子、盒子等都是

28、容器的具體化。由于BeanFactory只定義了最基本的IoC容器規(guī)范,所以,BeanFactory主要用在內(nèi)存、CPU資源受限場(chǎng)合,比如Applet、手持設(shè)備等,也就是小型應(yīng)用場(chǎng)景,企業(yè)級(jí)別的應(yīng)用通常需要使用BeanFactory的子接口,比如最常用的ApplicationContext接口。1.3.2 ApplicationContext容器BeanFactory提供了最基本的功能,而ApplicationContext則提供了更多的面向企業(yè)級(jí)應(yīng)用的功能,ApplicationContext是BeanFactory的子接口,所以,ApplicationContext擁有BeanFactor

29、y提供的所有功能。ApplicationContext提供了以下面向企業(yè)級(jí)應(yīng)用的功能:(1) 提供了文本信息解析工具,包括對(duì)國(guó)際化的支持。(2) 提供了載入文件資源的通用方法,如載入圖片。(3) 可以向注冊(cè)為監(jiān)聽器的Bean發(fā)送事件。由于它提供的附加功能,基本上中大型的應(yīng)用系統(tǒng)都會(huì)選擇ApplicationContext而不是BeanFactory。只有在資源很少的情況下,才會(huì)考慮采用BeanFactory,如在移動(dòng)設(shè)備上。在ApplicationContext的諸多實(shí)現(xiàn)中,有三個(gè)實(shí)現(xiàn)會(huì)經(jīng)常用到: ClassPathXmlApplicationContext類路徑中的XML文件載入上下文定義信

30、息,把上下文定義文件當(dāng)成類路徑資源。 FileSystemXmlApplicationContext從文件系統(tǒng)中的XML文件載入上下文定義信息。 XmlWebApplicationContext從Web系統(tǒng)中的XML文件載入上下文定義信息。BeanFactory與另一個(gè)重要區(qū)別是關(guān)于Bean的載入時(shí)機(jī)。BeanFactory延遲載入所有的Bean,直到getBean()方法被調(diào)用時(shí)Bean才被創(chuàng)建,這種方式的好處是即用即實(shí)例化,節(jié)約了內(nèi)存資源,所以常用于移動(dòng)設(shè)備。ApplicationContext則不同,它會(huì)在上下文啟動(dòng)后實(shí)例化所有的Bean,并通過預(yù)載入單實(shí)例Bean,確保需要的時(shí)候已經(jīng)準(zhǔn)

31、備充分。1.3.3 使用Spring IoC容器使用Spring的IoC容器來管理Bean通常需要以下幾步: 創(chuàng)建Bean的實(shí)現(xiàn)類。 使用XML文件配置元數(shù)據(jù),把Bean配置到XML文件中,讓Spring進(jìn)行管理。 實(shí)例化容器,獲得BeanFactory的實(shí)例。 通過BeanFactory獲取Spring IoC容器管理的實(shí)例。Spring 提供了強(qiáng)大的IoC容器來管理組成應(yīng)用程序的Bean。要利用容器提供的服務(wù),就必須創(chuàng)建需要的Bean類,并且配置Bean,讓這些Bean能夠被Spring IoC容器管理。在Spring IoC容器里可以通過XML文件、屬性文件甚至API來配置Bean。因?yàn)?/p>

32、基于XML的配置既簡(jiǎn)單又成熟,所以本書只基于XML進(jìn)行配置。如果對(duì)其他配置方法感興趣,可以自行查閱Spring的相關(guān)文檔,那里有更多關(guān)于Bean配置的信息。Spring允許使用一個(gè)或多個(gè)Bean配置文件來配置Bean。對(duì)于簡(jiǎn)單的應(yīng)用程序而言,可以將所有Bean集中配置于一個(gè)文件中。但是,對(duì)于大型的、擁有很多Bean的應(yīng)用程序而言,則應(yīng)該根據(jù)Bean的不同功能將它們分別配置到多個(gè)文件里。接下來采用Spring IoC容器管理的方式來完成前面介紹的打印機(jī)例子。1. 創(chuàng)建Bean類創(chuàng)建所需要的Bean類,創(chuàng)建一個(gè)抽象類Printer。和前例的不同在于增加了屬性,其中type表示打印機(jī)類型,manu表

33、示生產(chǎn)廠商,代碼如下:public abstract class Printer / 類型 String type; / 廠商 String manu; / 初始化方法 public abstract void init(); /打印 public abstract void print(String txt); public String getType() return type; public void setType(String type) this.type = type; public String getManu() return manu; public void setMa

34、nu(String manu) this.manu = manu; 再創(chuàng)建電腦類和Printer的子類,這兩個(gè)類和前面例子中所創(chuàng)建的一樣。2. 使用XML文件配置Bean使用XML文件配置元數(shù)據(jù),讓Spring能夠管理Bean的實(shí)例和依賴關(guān)系。要通過XML在Spring IoC容器里聲明Bean,首先需要?jiǎng)?chuàng)建XML Bean配置文件。我們計(jì)劃在項(xiàng)目的源代碼src目錄中創(chuàng)建一個(gè)名叫beans.xml的配置文件,然后寫出一個(gè)基于XML配置的基本結(jié)構(gòu)。在使用基于XML的方式配置元數(shù)據(jù)的時(shí)候,XML有一個(gè)根元素就是beans,我們需要在元素中添加一個(gè)或者多個(gè)元素。元素的配置根據(jù)需要和應(yīng)用程序中實(shí)際使用

35、的對(duì)象一一對(duì)應(yīng)。如果要在應(yīng)用程序中使用ColorPrinter的實(shí)例,那么可以采用如下配置: 同理,如果需要配置Computer的實(shí)例,則配置如下: 除了配置Bean的屬性外,還可以根據(jù)需要通過配置Bean的子標(biāo)簽來配置多個(gè)Bean之間的關(guān)系,以達(dá)到注入的目的。其中,Type3型的注入方式通過子標(biāo)簽實(shí)現(xiàn),Type2型的注入方式通過子標(biāo)簽實(shí)現(xiàn)。首先介紹標(biāo)簽的用法。1) property是最常用的子標(biāo)簽,它可以給Bean設(shè)置屬性。其中,name表示Bean的屬性名稱。通常屬性的值可以用以下方式賦予: 直接使用value。 使用value子元素。 使用ref子元素指向另一個(gè)Bean,指向的Bean必

36、須在配置文件中存在。需要注意的是該Bean的屬性必須提供set/get方法。假設(shè)有一個(gè)電腦類的表示如下:public class Computer / 生產(chǎn)廠商 String manu; / 型號(hào) String type; public String getType() return type; public void setType(String type) this.type = type; public String getManu() return manu; public void setManu(String manu) this.manu = manu; /打印機(jī) Printer

37、 p; /打印文本 public void printTxt(String txt) p.init(); p.print(txt); public Printer getP() return p; public void setP(Printer p) this.p = p; 則可以通過上面的三種方式來配置一個(gè)電腦類的實(shí)例: 蘋果 此外,property還可以包含集合元素,并通過、等配置與Java集合中的list、set、map對(duì)應(yīng),比如: China American England China American England 當(dāng)為簡(jiǎn)單類型的屬性賦值時(shí),Spring支持使用快捷方式??梢栽?/p>

38、元素里使用value屬性,以此取代在元素里內(nèi)附一個(gè)元素。比如,如下配置:為了方便定義屬性,可以采取另一種便利的快捷方式。這種方式通過使用p Schema來定義Bean屬性,其中p是元素的屬性。這種方式可以減少XML配置的代碼行數(shù)。2) 在Bean中嵌入多個(gè)子元素,通過名稱可以看出,這些子元素是給Bean的構(gòu)造函數(shù)注入值,即Type2類型的注入方式,這種注入有以下3種方式: 用type指定類型,value指定值。 用ref屬性引用另一個(gè)已經(jīng)配置好的Bean。 用ref子標(biāo)簽引用另一個(gè)已經(jīng)配置好的Bean。具體見下例: 在定義User類的時(shí)候,構(gòu)造函數(shù)需要有兩個(gè)參數(shù),其中User類的定義如下:pu

39、blic class User String name; String sex; int age;/聯(lián)系信息 ContactInfo cInfo; public User(String name,ContactInfo cInfo) = name; this.cInfo = cInfo; 用戶的聯(lián)系信息類ContactInfo的定義如下:public class ContactInfo String mobile; String address; String qq; public String getMobile() return mobile; public void setMobile(

40、String mobile) this.mobile = mobile; public String getAddress() return address; public void setAddress(String address) this.address = address; public String getQq() return qq; public void setQq(String qq) this.qq = qq; 3. 使用多模塊配置當(dāng)項(xiàng)目規(guī)模比較小的時(shí)候,只需要配置一個(gè)文件,但通常情況下,應(yīng)用Spring的項(xiàng)目規(guī)模都比較大,為了便于項(xiàng)目的管理和人員的分工協(xié)作,通常要把Sp

41、ring的配置文件按模塊進(jìn)行劃分,一般一個(gè)模塊需要一個(gè)配置文件,然后由一個(gè)總的配置文件把這些文件包含進(jìn)來。假設(shè)一個(gè)人力資源管理系統(tǒng)可能包含部門員工管理系統(tǒng)、招聘系統(tǒng)、工資系統(tǒng)、考勤系統(tǒng)、培訓(xùn)系統(tǒng)等5個(gè)模塊,那么就可以分5個(gè)模塊,并分別寫5個(gè)模塊的Spring配置文件,比如spring_employee.xml、spring_salary.xml、spring_job.xml、spring_checkin.xml、spring_train.xml,最后把這5個(gè)配置文件通過標(biāo)記導(dǎo)入到一個(gè)名叫spring_hr.xml的配置文件中。spring_hr.xml的配置如下: 這只是多文件配置方式中的一種

42、,在做Web開發(fā)和其他框架集成的時(shí)候,還會(huì)介紹其他多文件配置的方式。4. 實(shí)例化Spring容器使用配置文件定義好了容器管理的Bean之后,第三步就是在程序當(dāng)中獲取BeanFactory的實(shí)例,然后通過BeanFactory產(chǎn)生所需要的Bean的實(shí)例。獲取BeanFactory的實(shí)例的方式有多種,其中最常見的方式如下:方式一:實(shí)例化BeanFactory。要實(shí)例化BeanFactory,首先必須將Bean配置文件加載到Resource對(duì)象中。例如,下面的語句就對(duì)位于classpath根目錄下的配置文件進(jìn)行了加載。Resource resource = new ClassPathResource

43、(beans.xml);Resource僅僅是一個(gè)接口,ClassPathResource是它的一個(gè)實(shí)現(xiàn),ClassPathResource用于從Classpath加載資源。其他Resource接口的實(shí)現(xiàn),如FileSystemResource、InputStreamResource和UrlResource用于從其他位置加載資源。圖1-5顯示了在Spring里Resource接口的一般實(shí)現(xiàn)。接下來,使用上面加載配置文件生成的Resource對(duì)象,實(shí)例化BeanFactory。BeanFactory factory = new XmlBeanFactory(resource);BeanFacto

44、ry僅僅是一個(gè)接口,它對(duì)BeanFactory的操作進(jìn)行了抽象,XmlBeanFactory則是對(duì)它的具體實(shí)現(xiàn),用于從XML配置文件構(gòu)建BeanFactory,在Spring3.X版本中已經(jīng)建議不采用XmlBeanFactory的方式獲取BeanFactory,所以最好還是采用第二種方式。方式二:實(shí)例化ApplicationContext。和BeanFactory類似,ApplicationContext也只是一個(gè)接口,要使用ApplicationContext,首先必須實(shí)例化它的實(shí)現(xiàn)類。ClassPathXmlApplicationContext是ApplicationContext的實(shí)現(xiàn),

45、從classpath加載XML配置文件,然后構(gòu)建Application Context。也可以為其指定多個(gè)配置文件。 加載單個(gè)文件:ApplicationContext = new ClassPathXmlApplicationContext(beans.xml); 加載多個(gè)文件:ApplicationContext = new ClassPathXmlApplicationContext( new Stringbeans.xml,beans1.xml);除了ClassPathXmlApplicationContext,Spring還提供了一些其他的ApplicationContext實(shí)現(xiàn)。F

46、ileSystemXmlApplicationContext用于從文件系統(tǒng)加載XML配置文件,XmlWebApplicationContext只能用于Web應(yīng)用程序,XmlPortletApplicationContext只能用于門戶應(yīng)用程序。圖1-6顯示了Spring里ApplicationContext接口的一般實(shí)現(xiàn)。獲取BeanFactory后,就可以通過工廠獲取Bean的實(shí)例。5. 獲取Bean的實(shí)例要從Bean Factory或Application Context里獲取所聲明的Bean,需要調(diào)用getBean()方法,給這個(gè)方法傳入唯一的Bean名稱。因?yàn)樵摲椒ǚ祷氐膶?duì)象類型是ja

47、va.lang.Object,所以需要在使用返回對(duì)象之前將其他強(qiáng)制轉(zhuǎn)換為各自真正的類型,具體代碼如下:public class SpringTest /* * param args */ public static void main(String args) /獲取BeanFactory實(shí)例 ApplicationContext context = new ClassPathXmlApplicationContext(beans.xml); / 獲取 Computer實(shí)例 Computer p = (Computer)context.getBean(pc); p.printTxt(Hello

48、,Spring!); 2.1AOP基礎(chǔ)2.2通知和切面2.1AOP基礎(chǔ)2.1.1AOP概述如圖2-1所示,AOP采用橫向切割的方式,把橫切邏輯,即和業(yè)務(wù)本身無關(guān)的邏輯獨(dú)立出來,再根據(jù)需要把這些獨(dú)立的模塊織入到業(yè)務(wù)方法中。除了IoC容器,Spring Framework的另一個(gè)核心模塊就是AOP框架。但是,Spring的IoC模塊并不依賴于AOP,如果項(xiàng)目中不需要?jiǎng)t完全可以不使用AOP模塊。目前,市場(chǎng)上有很多種AOP框架,主流的只有以下三種開源的AOP框架。(1) AspectJ,5.0版本后與AspectWerkz合并。(2) JBoss AOP,它是JBoss應(yīng)用程序服務(wù)器項(xiàng)目的一個(gè)子項(xiàng)目。

49、(3) Spring AOP,它是Spring Framework的一部分。其中,AspectJ是Java社區(qū)里最完整、最流行的AOP框架。同時(shí),Spring AOP也提供了另外一種完整的AOP實(shí)現(xiàn),但它不是AspectJ的競(jìng)爭(zhēng)者,它的目的是給Spring IoC容器提供一種一致性集成的AOP解決方案。Spring AOP的設(shè)計(jì)理念是:無論開發(fā)人員采用什么樣的技術(shù),Spring都會(huì)提供一個(gè)融合這些技術(shù)的平臺(tái),所以,盡管Spring本身的AOP不是很強(qiáng)大,但是Spring本身提供了對(duì)AspectJ的封裝,以支持對(duì)AspectJ的使用。2.1.2 AOP常用術(shù)語AOP常用術(shù)語見下。(1) Join

50、Point:連接點(diǎn),在程序執(zhí)行過程中某個(gè)特定的點(diǎn)。(2) PointCut:切入點(diǎn),匹配連接點(diǎn)(JoinPoint);通知和一個(gè)切入點(diǎn)表達(dá)式關(guān)聯(lián),并在滿足這個(gè)切入點(diǎn)的連接點(diǎn)上運(yùn)行。(3) Advice:通知,在切點(diǎn)的某個(gè)特定連接點(diǎn)上執(zhí)行的動(dòng)作,它定義了切面是什么、什么時(shí)候使用。(4) Introduce:引入,可看作是一種特殊的通知,允許為已存在類添加新方法和屬性。例如,可以創(chuàng)建一個(gè)稽查通知來記錄對(duì)象的最后修改時(shí)間。只要用一個(gè)方法setLastModified(Date)以及一個(gè)保存這個(gè)狀態(tài)的變量,即可在不改變已存在類的情況下將狀態(tài)引入,設(shè)置新的行為和狀態(tài)。(5) Aspect:切面,由切入點(diǎn)

51、和通知組成,它既包括了橫切邏輯的定義,也包括了連接點(diǎn)的定義。(6) Target:目標(biāo)對(duì)象,通知對(duì)象織入的目標(biāo)對(duì)象,通常這個(gè)對(duì)象只需要關(guān)注業(yè)務(wù)邏輯操作,非業(yè)務(wù)的橫切邏輯在通知中,AOP可以動(dòng)態(tài)地把通知織入到這些目標(biāo)中。(7) Weaving:織入,采用某種方式把通知添加到目標(biāo)對(duì)象中的過程。圖2-2展示了AOP的關(guān)鍵概念。2.1.3 動(dòng)態(tài)代理使用代理的目的是不希望客戶直接訪問原始對(duì)象,這樣可以起到保護(hù)原始對(duì)象的作用,有時(shí)也可以屏蔽使用原始對(duì)象的細(xì)節(jié)。代理對(duì)象負(fù)責(zé)決定是否以及何時(shí)將方法調(diào)用轉(zhuǎn)發(fā)到原始對(duì)象上,此外,圍繞著每個(gè)方法的調(diào)用,代理對(duì)象也可以執(zhí)行一些額外任務(wù)。這樣的例子在實(shí)際生活中有很多,比

52、如服務(wù)器代理、防火墻代理、代理商等。代理模式是GOF23中經(jīng)典模式之一,其基本思想是給某一對(duì)象提供代理對(duì)象,并由代理對(duì)象控制具體對(duì)象的引用。圖2-3展示了代理設(shè)計(jì)模式的思路。在Java里,實(shí)現(xiàn)代理設(shè)計(jì)模式有兩種方法。一種是靜態(tài)代理,另一種是動(dòng)態(tài)代理。Spring AOP的核心實(shí)現(xiàn)技術(shù)是動(dòng)態(tài)代理。在JDK1.3以后,Java提供了動(dòng)態(tài)代理技術(shù),允許開發(fā)人員在運(yùn)行期間創(chuàng)建接口的代理實(shí)例。使用Java的代理類必須要求目標(biāo)類和代理類實(shí)現(xiàn)一個(gè)共同的接口。JDK的動(dòng)態(tài)代理類使用java.lang.reflect包中的兩個(gè)主要類:Proxy和InvocationHandler。其中,InvocationHa

53、ndler是一個(gè)接口,可以通過實(shí)現(xiàn)該接口定義橫切邏輯,并通過反射的機(jī)制調(diào)用目標(biāo)類代碼,動(dòng)態(tài)地把橫切邏輯和業(yè)務(wù)邏輯編織在一起。Proxy則是利用InvocationHandler動(dòng)態(tài)創(chuàng)建一個(gè)和目標(biāo)類接口相同的實(shí)例,從而產(chǎn)生目標(biāo)類的代理對(duì)象。舉例說明,有一個(gè)電腦類接口,代碼如下:public interface Computer /啟動(dòng) void start(); /停止 void stop(); /打印 void print();接口中有三個(gè)方法,分別表示:?jiǎn)?dòng)、停止和打印。接下來,寫一個(gè)簡(jiǎn)單的實(shí)現(xiàn):public class PC implements Computer Override pub

54、lic void start() System.out.println(啟動(dòng)電腦.); Override public void stop() System.out.println(停止電腦.); Override public void print() System.out.println(打印.); ComputerImpl做了一個(gè)簡(jiǎn)單的實(shí)現(xiàn),提示每個(gè)方法正在進(jìn)行的操作,現(xiàn)在需要給這個(gè)PC類的每個(gè)方法添加一個(gè)橫切的邏輯,希望在執(zhí)行每個(gè)方法之后,打印出該方法運(yùn)行的開始時(shí)間和結(jié)束時(shí)間。如果采用靜態(tài)代理的方法,則需要另外寫一個(gè)靜態(tài)代理類PCStaticProxy,其代碼如下:public cla

55、ss PCStaticProxy implements Computer /目標(biāo)類 PC pc = new PC(); Override public void start() System.out.println(new Date() + 開始運(yùn)行!); pc.start(); System.out.println(new Date() + 結(jié)束運(yùn)行!); Override public void stop() System.out.println(new Date() + 開始運(yùn)行!); pc.stop(); System.out.println(new Date() + 結(jié)束運(yùn)行!);

56、Override public void print() System.out.println(new Date() + 開始運(yùn)行!); pc.print(); System.out.println(new Date() + 結(jié)束運(yùn)行!); PCStaticProxy是PC的靜態(tài)代理類實(shí)現(xiàn)。PCStaticProxy中有一個(gè)pc屬性,這個(gè)屬性就是PCStaticProxy要代理的目標(biāo)類,PCStaticProxy所做的就是調(diào)用目標(biāo)類的方法,同時(shí)把橫切的代碼織入其中,這樣就完成了對(duì)PC類的靜態(tài)代理。在客戶端使用的時(shí)候,不再直接使用PC類,而是使用PC的代理類PCStaticProxy。由上面代碼

57、可以看出,使用靜態(tài)代理類實(shí)現(xiàn)代碼橫切幾乎要重寫目標(biāo)類代碼,增加了大量的重復(fù)性工作,并且一旦橫切代碼需要改變,就會(huì)引起大量的代碼改動(dòng),極不利于代碼的維護(hù),若使用動(dòng)態(tài)代理則不會(huì)出現(xiàn)上述問題,下面來看看動(dòng)態(tài)代理是如何實(shí)現(xiàn)的。使用動(dòng)態(tài)代理類首先需要實(shí)現(xiàn)InvocationHandler接口。InvocationHandler接口表示如下:package java.lang.reflect;public interface InvocationHandler public Object invoke(Object proxy,Method method,Object args) throws Throw

58、able; 接口中聲明方法invoke(),在方法中控制整個(gè)調(diào)用過程。invoke()方法的第一個(gè)參數(shù)是最終產(chǎn)生的代理實(shí)例,第二個(gè)參數(shù)是表示被代理的目標(biāo)實(shí)例的方法名,最后一個(gè)參數(shù)是表示被調(diào)用的目標(biāo)方法的參數(shù)數(shù)組。事實(shí)上,可以將接口看成一個(gè)織入器,在invoke方法中,可以把需要織入的橫切代碼和目標(biāo)代碼編織在一起。本例中,創(chuàng)建一個(gè)PCHandler類實(shí)現(xiàn)接口InvocationHandler:public class PCHandler implements InvocationHandler / 代理類 Object target; public PCHandler(Object target

59、) this.target = target; Override public Object invoke(Object proxy, Method method, Object args) throws Throwable Object obj = null; System.out.println(method.getName() + 于: + new Date() + 開始運(yùn)行!); obj = method.invoke(this.target, args); System.out.println(method.getName() + 于: + new Date() + 結(jié)束運(yùn)行!);

60、return obj; 該實(shí)現(xiàn)類中有一個(gè)target屬性,表示需要代理的目標(biāo)類,實(shí)現(xiàn)類實(shí)例化的時(shí)候需要知道這個(gè)目標(biāo)類。以下代碼利用了Java中的反射技術(shù)執(zhí)行目標(biāo)類的方法:obj = method.invoke(this.target, args);PCHandler只相當(dāng)于一個(gè)代碼織入器,并沒有產(chǎn)生最終的代理類。產(chǎn)生代理類需要使用Proxy類的newInstance方法,其聲明如下:public static Object newProxyInstance(ClassLoader loader,Class interfaces, InvocationHandler h)該方法需要三個(gè)參數(shù),第一

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。

評(píng)論

0/150

提交評(píng)論