




版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認領(lǐng)
文檔簡介
1、1.1Spring簡介1.2IoC容器1.3 Spring IoC容器1.1Spring簡介Spring是一個開源框架,它由Rod Johnson創(chuàng)建。Spring誕生之初是為了解決企業(yè)應(yīng)用軟件開發(fā)日益復(fù)雜的難題。Spring創(chuàng)建的初衷如下:(1) J2EE應(yīng)該更加簡單。(2) 使用接口而不是使用類,是更好的編程習(xí)慣。(3) 為JavaBean提供了一個更好的應(yīng)用配置框架。(4) 更多地強調(diào)面向?qū)ο蟮脑O(shè)計,而不是現(xiàn)行的技術(shù)。(5) 盡量減少不必要的異常捕捉。(6) 使應(yīng)用程序更加容易測試。Spring框架目標:(1) 可以令人方便愉快地使用Spring。(2) 應(yīng)用程序代碼并不依賴于Sprin
2、g API。(3) Spring不是和現(xiàn)有的解決方案競爭,而是致力于與現(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等幾個主要版本,目前發(fā)布的版本增加了許多特性,比如Spring表達式語言、IoC增強、聲明模型驗證、更多的注解支持和嵌入式數(shù)據(jù)庫支持等。1.1.2Spring項目簡介圍繞著Spring框架本身,有許多優(yōu)秀的項目,此處只對Spring的常用項目進行簡單介紹。(1) Spring Framework(Core)
3、:整個Spring項目的核心。(2) Spring Web Flow:定義了一種特定的語言來描述工作流,且其高級的工作流控制器引擎可以管理會話狀態(tài),支持AJAX來構(gòu)建豐富的客戶端體驗,還能對JSF提供支持。(3) Spring Security:廣泛使用的基于Spring的認證和安全工具。(4) Spring Dynamic Modules:可以讓Spring應(yīng)用運行在OSGi平臺上。(5) Spring Batch:提供構(gòu)建批處理應(yīng)用和自動化操作的框架。(6) Spring Android:為Android終端開發(fā)應(yīng)用提供Spring支持,并提供了一個基于Jave的在Android應(yīng)用環(huán)境中
4、工作的REST客戶端。(7) Spring Mobile:是基于Spring MVC構(gòu)建的,可為移動終端的服務(wù)器應(yīng)用開發(fā)提供支持。(8) Spring Social:Spring框架的擴展,可以幫助Spring應(yīng)用更方便地使用SNS(Social Network Service)。所有基于Spring的項目都是以Spring Framework為基礎(chǔ)開發(fā)出來的。事實上,Spring Framework也是Spring體系的核心。作為平臺,Spring將許多應(yīng)用開發(fā)中遇到的共性問題進行了抽象;同時,作為一個輕量級的應(yīng)用開發(fā)框架,Spring和傳統(tǒng)的J2EE開發(fā)相比,有其自身特點。通過這些自身特點
5、,Spring充分體現(xiàn)了它的設(shè)計理念:支持POJO和使用JavaBean的開發(fā)方式、面向接口開發(fā)、支持OO(面向?qū)ο?的設(shè)計方法。到目前為止,Spring Framework一共包含大約20個模塊,這些模塊大多集中在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注冊器的框架式對象訪問方法。(3) Expression Language模塊:提供了一個強大的表達式語言,可以在運行時查詢和操縱對象。2. Data Access/IntegrationData Access/Integration部分包含JDBC、ORM、OXM、JMS和Transaction等模塊。(1) JDBC模塊:提供了一個JDBC抽象層,可以消除冗長的JDBC編碼和解析數(shù)據(jù)
7、庫廠商特有的錯誤代碼。(2) ORM模塊:為流行的對象/關(guān)系映射APIJPA、JDO、Hibernate、iBatis等提供了一個交互層。(3) OXM模塊:提供了一個對Object/XML映射實現(xiàn)的抽象層。(4) JMS(Java Messaging Service)模塊:主要包含制造和消費消息的特性。(5) Transaction模塊:支持編程和聲明性的事務(wù)管理,這些事務(wù)類必須實現(xiàn)特定的接口,并且對所有的POJO都適用。3. WebWeb部分包含Web、Servlet、Struts、Porlet等模塊。(1) Web模塊:提供了基礎(chǔ)的面向Web的集成特性,它還包含Spring遠程支持中的W
8、eb相關(guān)部分。(2) Servlet模塊:包含Spring的Model-View-Controller(MVC)實現(xiàn)。(3) Struts模塊:提供了對Struts的支持,使得類在Spring應(yīng)用中能夠與一個典型的Struts Web層集成在一起。(4) Portlet模塊:提供了用于Portlet環(huán)境和Web-Servlet模塊的MVC實現(xiàn)。4. AOPAOP即面向切面編程。在程序開發(fā)中AOP可以解決一些系統(tǒng)層面的問題。5. Instrumentation和TestInstrumentation模塊提供了Class Instrumentation支持和ClassLoader實現(xiàn),可以在某些特
9、定的應(yīng)用服務(wù)器上使用。Test模塊支持使用JUnit和TestNG對Spring組件進行測試。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各模塊的項目源代碼,包含Eclipse項目文件和
10、Maven項目構(gòu)建配置文件。src:打包按功能存放的Spring Framework各模塊的項目源代碼,只含有源碼,不含項目配置文件。在創(chuàng)建Java項目后,如果需要使用Spring Framework,則要根據(jù)需要導(dǎo)入dist目錄下面相關(guān)的jar包。為了方便項目的管理,可以使用Eclipse自定義庫,把Spring Framework的相關(guān)文件放到用戶自定義庫中,當創(chuàng)建項目時可直接使用該庫。創(chuàng)建自定義庫的方式如圖1-3所示,在Eclipse菜單中選擇WindowPreferencesJavaBuild PathUser Libraries,然后點擊“New”新建用戶自定義庫,新建完畢后,選擇“
11、Add JARs”添加上述所有的jar包,再選擇“OK”,即可完成用戶自定義庫的創(chuàng)建。完成用戶自定義庫的創(chuàng)建后,當創(chuàng)建Java項目時,可以在創(chuàng)建的配置向?qū)е袑?dǎo)入用戶自定義庫,如圖1-4所示。配置好Spring開發(fā)環(huán)境后就可以使用Spring框架進行開發(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è)計領(lǐng)域的一種軟件設(shè)
12、計原則。依賴倒置原則基于這樣一個事實:相對于細節(jié)的多變性,抽象的東西要穩(wěn)定得多。即,以抽象為基礎(chǔ)搭建起來的架構(gòu)比以細節(jié)為基礎(chǔ)搭建起來的架構(gòu)要穩(wěn)定得多。在Java中,抽象指的是接口或者抽象類,細節(jié)就是具體的實現(xiàn)類,使用接口或者抽象類的目的是制定好規(guī)范和契約,而不去涉及任何具體的操作,把展現(xiàn)細節(jié)的任務(wù)交給實現(xiàn)類去完成。依賴倒置原則的核心思想是面向接口編程,使用接口是實現(xiàn)解耦合的最重要的途徑,此處用一個例子來說明面向接口編程比面向?qū)崿F(xiàn)編程好的原因。假設(shè)現(xiàn)在有一臺電腦需要安裝打印機,但目前只有一種類型的打印機可選,即黑白打印機。首先,設(shè)計打印機類:public class GrayPrinter /初
13、始化方法 public void init() System.out.println(啟動打印機!); /打印 public void print(String txt) System.out.println(打印黑白文字:.concat(txt); 此處,設(shè)計打印機類有兩個方法,一個是init啟動,另一個是print打印方法。其次,設(shè)計電腦類: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); 在電腦類中有一個打印機屬性和一個打印方法。最后,為測試類代碼:public class TestComputer /* * param args */ public static void main(String args) / TODO Auto-generated method stub /創(chuàng)建電腦 Computer pc1 = new Computer(); /創(chuàng)建打印機 GrayPrinter p = new GrayPrinter(); pc1.setP(p); /打印文本
15、pc1.getP().print(打印測試頁.); 運行測試代碼,得到需要的打印結(jié)果。過了幾年,人們發(fā)現(xiàn)這個世界還是彩色的比較好看,于是發(fā)明了彩色打印機,此時打印機的選擇就變多了,為了實現(xiàn)彩色打印不得不多寫一個彩色打印機類,并修改電腦類。又過了幾年,人們發(fā)現(xiàn)激光打印機更清晰,于是,又需要修改電腦類總之,每次有新的打印機上市,就需要修改電腦類的代碼。事實上這是一個典型的依賴具體實現(xiàn)的例子電腦類對GrayPrinter產(chǎn)生了依賴,一旦有新型的打印機產(chǎn)生(即產(chǎn)生新的ColorPrinter、LazerPrinter等),就需要修改電腦類代碼。根據(jù)依賴倒置原則描述的,調(diào)用者應(yīng)該依賴被調(diào)用者的抽象,而不
16、是依賴于它的具體實現(xiàn),此時可以抽象出一個Printer接口,其他的具體實現(xiàn)類都靠這個接口實現(xiàn),這樣修改后,無論以后怎樣擴展Printer類,都不需要再修改電腦類了。修改之后的代碼如下。Printer接口:public interface Printer /初始化方法 void init(); /打印 void print(String txt);GrayPrinter黑白打印機:public class GrayPrinter implements Printer /初始化方法 Override public void init() System.out.println(啟動打印機!); /打
17、印 Override public void print(String txt) System.out.println(打印黑白文字:.concat(txt); ColorPrinter彩色打印機:public class ColorPrinter implements Printer /初始化方法 Override public void init() System.out.println(啟動彩色打印機!); /打印 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; 此時電腦類依賴的是Printer這個抽象接口,而不是依賴于Printer的具體實現(xiàn)。但在測試類中又存在相似的問題,比如現(xiàn)在需要彩色打印機,具體代碼如下: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)建打印機 Printer p = new ColorPrinter(); pc1.setP(p); /打印文本 pc1.getP().print(打印測試頁.); 在上述TestComputer測試類中,使用了new ColorPrinter方式創(chuàng)建Printer實例,假設(shè)把所有彩色打印機換成黑白的,則要修改TestComputer測試類中的代碼。為了減少修改代碼的次數(shù),可以寫一個配置文件,配置具體需要實
20、例化的類,然后在TestComputer測試類中讀取配置文件,再根據(jù)配置產(chǎn)生不同的實例。此時TestComputer測試類的改變?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)建實例 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(無法實例化對象!); 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)建打印機 Printer p = (Printer)TestComputer.getBean(printer); pc1.setP(p); /打印文本 pc1.getP().print(打印測試頁.); 可以看到,上述TestComputer測試類代碼在靜態(tài)塊中讀取了perties配置文件,同時提供了一個getBean方法,該方法可以根據(jù)perties的配置來實例化一個類,在給電腦裝配打印機的時候,不再采用new的方式直接實例化對象,而是通過調(diào)用getBean的方式獲取一個根據(jù)業(yè)務(wù)需要產(chǎn)生的具體實例。perties的代碼如下:printer=com.ssoft.ssh.demo2
23、.ColorPrinter#com.ssoft.ssh.demo2.GrayPrinter這里perties定義了一個名叫printer的主鍵,值是ColorPrinter類的全名,當然,也可以根據(jù)具體的需要切換成GrayPrinter類。如此配置之后即可根據(jù)具體的業(yè)務(wù)需要產(chǎn)生不同的、和業(yè)務(wù)相關(guān)的Printer實例給TestComputer測試類使用,即便以后有了新類型的Printer,也不需要修改TestComputer測試類,只需要添加一個Printer的實現(xiàn)類,這樣,可以讓應(yīng)用程序具有很好的擴展能力。需要注意的是,運用很多設(shè)計模式或者類設(shè)計原則的時候并不會減少代碼量,相反會增加一定量的代
24、碼,但這樣做的好處是增強程序的擴展能力,提高程序的維護性。在理解了上述例子之后,此時再講Spring的IoC容器就比較容易理解了。容器是用來裝東西的,Spring的IoC容器就是用來裝Bean實例的,然后把這些實例通過配置的方式注入調(diào)用者中,而不是直接在代碼中硬編碼實例對象,所以,IoC也叫作DI依賴注入(Dependency Injection)。1.2.2 依賴注入類型依賴注入通常分為三類,分別是接口注入(Type1型)、構(gòu)造器注入(Type2型)和setter注入(Type3型),其中Type2型和Type3型是比較常用的類型,尤其Type3型是使用最多的注入方式。所謂setter注入,
25、就是指調(diào)用者類提供一個setter方法,把被調(diào)用者作為參數(shù)傳遞給調(diào)用者,比如前面的電腦類代碼中有一個Printer屬性,我們通過setPrinter的方法把Printer對象的實例傳遞給它,這就是典型的setter注入方式。構(gòu)造器注入方式,表示的是調(diào)用者在實例化的時候必須注入被調(diào)用者的實例。若把上例改成構(gòu)造器注入,則電腦類代碼就必須改成如下方式:public class Computer Printer p; public Computer(Printer p) this.p = p; 在創(chuàng)建電腦類實例的時候,必須把Printer的實例注入給Computer實例:Computer c = ne
26、w Computer(new ColorPrinter();若把上例改成接口注入的方式,則電腦類必須實現(xiàn)一個接口,其代碼如下: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)用者必須實現(xiàn)一個指定的接口,典型的應(yīng)用有EJB(這種方式使用比較少,一般不推薦)。Spring IoC容器提供了Type2和Type3型的注入方式。1.3 Spring IoC容器1.3.1 BeanFactory容器BeanFactory采用工廠模式,提供了最基本的IoC容器功能:實例化對象、配置對象之間的依賴關(guān)系。在Spring中,所有的對象都是由BeanFactory工廠來生產(chǎn)管理的。BeanFactory只是一個接口類,它定義了IoC容器的一個標準,卻沒有給出容器的具體實現(xiàn),因此還需要依靠具體的實現(xiàn)類。通俗地講,BeanFactory如同生活中定義的容器,而瓶子、罐子、盒子等都是
28、容器的具體化。由于BeanFactory只定義了最基本的IoC容器規(guī)范,所以,BeanFactory主要用在內(nèi)存、CPU資源受限場合,比如Applet、手持設(shè)備等,也就是小型應(yīng)用場景,企業(yè)級別的應(yīng)用通常需要使用BeanFactory的子接口,比如最常用的ApplicationContext接口。1.3.2 ApplicationContext容器BeanFactory提供了最基本的功能,而ApplicationContext則提供了更多的面向企業(yè)級應(yīng)用的功能,ApplicationContext是BeanFactory的子接口,所以,ApplicationContext擁有BeanFactor
29、y提供的所有功能。ApplicationContext提供了以下面向企業(yè)級應(yīng)用的功能:(1) 提供了文本信息解析工具,包括對國際化的支持。(2) 提供了載入文件資源的通用方法,如載入圖片。(3) 可以向注冊為監(jiān)聽器的Bean發(fā)送事件。由于它提供的附加功能,基本上中大型的應(yīng)用系統(tǒng)都會選擇ApplicationContext而不是BeanFactory。只有在資源很少的情況下,才會考慮采用BeanFactory,如在移動設(shè)備上。在ApplicationContext的諸多實現(xiàn)中,有三個實現(xiàn)會經(jīng)常用到: ClassPathXmlApplicationContext類路徑中的XML文件載入上下文定義信
30、息,把上下文定義文件當成類路徑資源。 FileSystemXmlApplicationContext從文件系統(tǒng)中的XML文件載入上下文定義信息。 XmlWebApplicationContext從Web系統(tǒng)中的XML文件載入上下文定義信息。BeanFactory與另一個重要區(qū)別是關(guān)于Bean的載入時機。BeanFactory延遲載入所有的Bean,直到getBean()方法被調(diào)用時Bean才被創(chuàng)建,這種方式的好處是即用即實例化,節(jié)約了內(nèi)存資源,所以常用于移動設(shè)備。ApplicationContext則不同,它會在上下文啟動后實例化所有的Bean,并通過預(yù)載入單實例Bean,確保需要的時候已經(jīng)準
31、備充分。1.3.3 使用Spring IoC容器使用Spring的IoC容器來管理Bean通常需要以下幾步: 創(chuàng)建Bean的實現(xiàn)類。 使用XML文件配置元數(shù)據(jù),把Bean配置到XML文件中,讓Spring進行管理。 實例化容器,獲得BeanFactory的實例。 通過BeanFactory獲取Spring IoC容器管理的實例。Spring 提供了強大的IoC容器來管理組成應(yīng)用程序的Bean。要利用容器提供的服務(wù),就必須創(chuàng)建需要的Bean類,并且配置Bean,讓這些Bean能夠被Spring IoC容器管理。在Spring IoC容器里可以通過XML文件、屬性文件甚至API來配置Bean。因為
32、基于XML的配置既簡單又成熟,所以本書只基于XML進行配置。如果對其他配置方法感興趣,可以自行查閱Spring的相關(guān)文檔,那里有更多關(guān)于Bean配置的信息。Spring允許使用一個或多個Bean配置文件來配置Bean。對于簡單的應(yīng)用程序而言,可以將所有Bean集中配置于一個文件中。但是,對于大型的、擁有很多Bean的應(yīng)用程序而言,則應(yīng)該根據(jù)Bean的不同功能將它們分別配置到多個文件里。接下來采用Spring IoC容器管理的方式來完成前面介紹的打印機例子。1. 創(chuàng)建Bean類創(chuàng)建所需要的Bean類,創(chuàng)建一個抽象類Printer。和前例的不同在于增加了屬性,其中type表示打印機類型,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的子類,這兩個類和前面例子中所創(chuàng)建的一樣。2. 使用XML文件配置Bean使用XML文件配置元數(shù)據(jù),讓Spring能夠管理Bean的實例和依賴關(guān)系。要通過XML在Spring IoC容器里聲明Bean,首先需要創(chuàng)建XML Bean配置文件。我們計劃在項目的源代碼src目錄中創(chuàng)建一個名叫beans.xml的配置文件,然后寫出一個基于XML配置的基本結(jié)構(gòu)。在使用基于XML的方式配置元數(shù)據(jù)的時候,XML有一個根元素就是beans,我們需要在元素中添加一個或者多個元素。元素的配置根據(jù)需要和應(yīng)用程序中實際使用
35、的對象一一對應(yīng)。如果要在應(yīng)用程序中使用ColorPrinter的實例,那么可以采用如下配置: 同理,如果需要配置Computer的實例,則配置如下: 除了配置Bean的屬性外,還可以根據(jù)需要通過配置Bean的子標簽來配置多個Bean之間的關(guān)系,以達到注入的目的。其中,Type3型的注入方式通過子標簽實現(xiàn),Type2型的注入方式通過子標簽實現(xiàn)。首先介紹標簽的用法。1) property是最常用的子標簽,它可以給Bean設(shè)置屬性。其中,name表示Bean的屬性名稱。通常屬性的值可以用以下方式賦予: 直接使用value。 使用value子元素。 使用ref子元素指向另一個Bean,指向的Bean必
36、須在配置文件中存在。需要注意的是該Bean的屬性必須提供set/get方法。假設(shè)有一個電腦類的表示如下:public class Computer / 生產(chǎn)廠商 String manu; / 型號 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; /打印機 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; 則可以通過上面的三種方式來配置一個電腦類的實例: 蘋果 此外,property還可以包含集合元素,并通過、等配置與Java集合中的list、set、map對應(yīng),比如: China American England China American England 當為簡單類型的屬性賦值時,Spring支持使用快捷方式。可以在
38、元素里使用value屬性,以此取代在元素里內(nèi)附一個元素。比如,如下配置:為了方便定義屬性,可以采取另一種便利的快捷方式。這種方式通過使用p Schema來定義Bean屬性,其中p是元素的屬性。這種方式可以減少XML配置的代碼行數(shù)。2) 在Bean中嵌入多個子元素,通過名稱可以看出,這些子元素是給Bean的構(gòu)造函數(shù)注入值,即Type2類型的注入方式,這種注入有以下3種方式: 用type指定類型,value指定值。 用ref屬性引用另一個已經(jīng)配置好的Bean。 用ref子標簽引用另一個已經(jīng)配置好的Bean。具體見下例: 在定義User類的時候,構(gòu)造函數(shù)需要有兩個參數(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. 使用多模塊配置當項目規(guī)模比較小的時候,只需要配置一個文件,但通常情況下,應(yīng)用Spring的項目規(guī)模都比較大,為了便于項目的管理和人員的分工協(xié)作,通常要把Sp
41、ring的配置文件按模塊進行劃分,一般一個模塊需要一個配置文件,然后由一個總的配置文件把這些文件包含進來。假設(shè)一個人力資源管理系統(tǒng)可能包含部門員工管理系統(tǒng)、招聘系統(tǒng)、工資系統(tǒng)、考勤系統(tǒng)、培訓(xùn)系統(tǒng)等5個模塊,那么就可以分5個模塊,并分別寫5個模塊的Spring配置文件,比如spring_employee.xml、spring_salary.xml、spring_job.xml、spring_checkin.xml、spring_train.xml,最后把這5個配置文件通過標記導(dǎo)入到一個名叫spring_hr.xml的配置文件中。spring_hr.xml的配置如下: 這只是多文件配置方式中的一種
42、,在做Web開發(fā)和其他框架集成的時候,還會介紹其他多文件配置的方式。4. 實例化Spring容器使用配置文件定義好了容器管理的Bean之后,第三步就是在程序當中獲取BeanFactory的實例,然后通過BeanFactory產(chǎn)生所需要的Bean的實例。獲取BeanFactory的實例的方式有多種,其中最常見的方式如下:方式一:實例化BeanFactory。要實例化BeanFactory,首先必須將Bean配置文件加載到Resource對象中。例如,下面的語句就對位于classpath根目錄下的配置文件進行了加載。Resource resource = new ClassPathResource
43、(beans.xml);Resource僅僅是一個接口,ClassPathResource是它的一個實現(xiàn),ClassPathResource用于從Classpath加載資源。其他Resource接口的實現(xiàn),如FileSystemResource、InputStreamResource和UrlResource用于從其他位置加載資源。圖1-5顯示了在Spring里Resource接口的一般實現(xiàn)。接下來,使用上面加載配置文件生成的Resource對象,實例化BeanFactory。BeanFactory factory = new XmlBeanFactory(resource);BeanFacto
44、ry僅僅是一個接口,它對BeanFactory的操作進行了抽象,XmlBeanFactory則是對它的具體實現(xiàn),用于從XML配置文件構(gòu)建BeanFactory,在Spring3.X版本中已經(jīng)建議不采用XmlBeanFactory的方式獲取BeanFactory,所以最好還是采用第二種方式。方式二:實例化ApplicationContext。和BeanFactory類似,ApplicationContext也只是一個接口,要使用ApplicationContext,首先必須實例化它的實現(xiàn)類。ClassPathXmlApplicationContext是ApplicationContext的實現(xiàn),
45、從classpath加載XML配置文件,然后構(gòu)建Application Context。也可以為其指定多個配置文件。 加載單個文件:ApplicationContext = new ClassPathXmlApplicationContext(beans.xml); 加載多個文件:ApplicationContext = new ClassPathXmlApplicationContext( new Stringbeans.xml,beans1.xml);除了ClassPathXmlApplicationContext,Spring還提供了一些其他的ApplicationContext實現(xiàn)。F
46、ileSystemXmlApplicationContext用于從文件系統(tǒng)加載XML配置文件,XmlWebApplicationContext只能用于Web應(yīng)用程序,XmlPortletApplicationContext只能用于門戶應(yīng)用程序。圖1-6顯示了Spring里ApplicationContext接口的一般實現(xiàn)。獲取BeanFactory后,就可以通過工廠獲取Bean的實例。5. 獲取Bean的實例要從Bean Factory或Application Context里獲取所聲明的Bean,需要調(diào)用getBean()方法,給這個方法傳入唯一的Bean名稱。因為該方法返回的對象類型是ja
47、va.lang.Object,所以需要在使用返回對象之前將其他強制轉(zhuǎn)換為各自真正的類型,具體代碼如下:public class SpringTest /* * param args */ public static void main(String args) /獲取BeanFactory實例 ApplicationContext context = new ClassPathXmlApplicationContext(beans.xml); / 獲取 Computer實例 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)的邏輯獨立出來,再根據(jù)需要把這些獨立的模塊織入到業(yè)務(wù)方法中。除了IoC容器,Spring Framework的另一個核心模塊就是AOP框架。但是,Spring的IoC模塊并不依賴于AOP,如果項目中不需要則完全可以不使用AOP模塊。目前,市場上有很多種AOP框架,主流的只有以下三種開源的AOP框架。(1) AspectJ,5.0版本后與AspectWerkz合并。(2) JBoss AOP,它是JBoss應(yīng)用程序服務(wù)器項目的一個子項目。
49、(3) Spring AOP,它是Spring Framework的一部分。其中,AspectJ是Java社區(qū)里最完整、最流行的AOP框架。同時,Spring AOP也提供了另外一種完整的AOP實現(xiàn),但它不是AspectJ的競爭者,它的目的是給Spring IoC容器提供一種一致性集成的AOP解決方案。Spring AOP的設(shè)計理念是:無論開發(fā)人員采用什么樣的技術(shù),Spring都會提供一個融合這些技術(shù)的平臺,所以,盡管Spring本身的AOP不是很強大,但是Spring本身提供了對AspectJ的封裝,以支持對AspectJ的使用。2.1.2 AOP常用術(shù)語AOP常用術(shù)語見下。(1) Join
50、Point:連接點,在程序執(zhí)行過程中某個特定的點。(2) PointCut:切入點,匹配連接點(JoinPoint);通知和一個切入點表達式關(guān)聯(lián),并在滿足這個切入點的連接點上運行。(3) Advice:通知,在切點的某個特定連接點上執(zhí)行的動作,它定義了切面是什么、什么時候使用。(4) Introduce:引入,可看作是一種特殊的通知,允許為已存在類添加新方法和屬性。例如,可以創(chuàng)建一個稽查通知來記錄對象的最后修改時間。只要用一個方法setLastModified(Date)以及一個保存這個狀態(tài)的變量,即可在不改變已存在類的情況下將狀態(tài)引入,設(shè)置新的行為和狀態(tài)。(5) Aspect:切面,由切入點
51、和通知組成,它既包括了橫切邏輯的定義,也包括了連接點的定義。(6) Target:目標對象,通知對象織入的目標對象,通常這個對象只需要關(guān)注業(yè)務(wù)邏輯操作,非業(yè)務(wù)的橫切邏輯在通知中,AOP可以動態(tài)地把通知織入到這些目標中。(7) Weaving:織入,采用某種方式把通知添加到目標對象中的過程。圖2-2展示了AOP的關(guān)鍵概念。2.1.3 動態(tài)代理使用代理的目的是不希望客戶直接訪問原始對象,這樣可以起到保護原始對象的作用,有時也可以屏蔽使用原始對象的細節(jié)。代理對象負責(zé)決定是否以及何時將方法調(diào)用轉(zhuǎn)發(fā)到原始對象上,此外,圍繞著每個方法的調(diào)用,代理對象也可以執(zhí)行一些額外任務(wù)。這樣的例子在實際生活中有很多,比
52、如服務(wù)器代理、防火墻代理、代理商等。代理模式是GOF23中經(jīng)典模式之一,其基本思想是給某一對象提供代理對象,并由代理對象控制具體對象的引用。圖2-3展示了代理設(shè)計模式的思路。在Java里,實現(xiàn)代理設(shè)計模式有兩種方法。一種是靜態(tài)代理,另一種是動態(tài)代理。Spring AOP的核心實現(xiàn)技術(shù)是動態(tài)代理。在JDK1.3以后,Java提供了動態(tài)代理技術(shù),允許開發(fā)人員在運行期間創(chuàng)建接口的代理實例。使用Java的代理類必須要求目標類和代理類實現(xiàn)一個共同的接口。JDK的動態(tài)代理類使用java.lang.reflect包中的兩個主要類:Proxy和InvocationHandler。其中,InvocationHa
53、ndler是一個接口,可以通過實現(xiàn)該接口定義橫切邏輯,并通過反射的機制調(diào)用目標類代碼,動態(tài)地把橫切邏輯和業(yè)務(wù)邏輯編織在一起。Proxy則是利用InvocationHandler動態(tài)創(chuàng)建一個和目標類接口相同的實例,從而產(chǎn)生目標類的代理對象。舉例說明,有一個電腦類接口,代碼如下:public interface Computer /啟動 void start(); /停止 void stop(); /打印 void print();接口中有三個方法,分別表示:啟動、停止和打印。接下來,寫一個簡單的實現(xiàn):public class PC implements Computer Override pub
54、lic void start() System.out.println(啟動電腦.); Override public void stop() System.out.println(停止電腦.); Override public void print() System.out.println(打印.); ComputerImpl做了一個簡單的實現(xiàn),提示每個方法正在進行的操作,現(xiàn)在需要給這個PC類的每個方法添加一個橫切的邏輯,希望在執(zhí)行每個方法之后,打印出該方法運行的開始時間和結(jié)束時間。如果采用靜態(tài)代理的方法,則需要另外寫一個靜態(tài)代理類PCStaticProxy,其代碼如下:public cla
55、ss PCStaticProxy implements Computer /目標類 PC pc = new PC(); Override public void start() System.out.println(new Date() + 開始運行!); pc.start(); System.out.println(new Date() + 結(jié)束運行!); Override public void stop() System.out.println(new Date() + 開始運行!); pc.stop(); System.out.println(new Date() + 結(jié)束運行!);
56、Override public void print() System.out.println(new Date() + 開始運行!); pc.print(); System.out.println(new Date() + 結(jié)束運行!); PCStaticProxy是PC的靜態(tài)代理類實現(xiàn)。PCStaticProxy中有一個pc屬性,這個屬性就是PCStaticProxy要代理的目標類,PCStaticProxy所做的就是調(diào)用目標類的方法,同時把橫切的代碼織入其中,這樣就完成了對PC類的靜態(tài)代理。在客戶端使用的時候,不再直接使用PC類,而是使用PC的代理類PCStaticProxy。由上面代碼
57、可以看出,使用靜態(tài)代理類實現(xiàn)代碼橫切幾乎要重寫目標類代碼,增加了大量的重復(fù)性工作,并且一旦橫切代碼需要改變,就會引起大量的代碼改動,極不利于代碼的維護,若使用動態(tài)代理則不會出現(xiàn)上述問題,下面來看看動態(tài)代理是如何實現(xiàn)的。使用動態(tài)代理類首先需要實現(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(),在方法中控制整個調(diào)用過程。invoke()方法的第一個參數(shù)是最終產(chǎn)生的代理實例,第二個參數(shù)是表示被代理的目標實例的方法名,最后一個參數(shù)是表示被調(diào)用的目標方法的參數(shù)數(shù)組。事實上,可以將接口看成一個織入器,在invoke方法中,可以把需要織入的橫切代碼和目標代碼編織在一起。本例中,創(chuàng)建一個PCHandler類實現(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() + 開始運行!); obj = method.invoke(this.target, args); System.out.println(method.getName() + 于: + new Date() + 結(jié)束運行!);
60、return obj; 該實現(xiàn)類中有一個target屬性,表示需要代理的目標類,實現(xiàn)類實例化的時候需要知道這個目標類。以下代碼利用了Java中的反射技術(shù)執(zhí)行目標類的方法:obj = method.invoke(this.target, args);PCHandler只相當于一個代碼織入器,并沒有產(chǎn)生最終的代理類。產(chǎn)生代理類需要使用Proxy類的newInstance方法,其聲明如下:public static Object newProxyInstance(ClassLoader loader,Class interfaces, InvocationHandler h)該方法需要三個參數(shù),第一
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 二零二五年度雇主免責(zé)協(xié)議書:航空航天領(lǐng)域雇主責(zé)任界定合同
- 2025年度產(chǎn)業(yè)轉(zhuǎn)型升級信息咨詢服務(wù)合同
- 2025年度農(nóng)產(chǎn)品質(zhì)量安全監(jiān)管與風(fēng)險評估合作協(xié)議
- 2025年度國際會展中心招商合作合同協(xié)議
- 2025年度臨時工臨時性數(shù)據(jù)錄入與處理合同
- 2025年度出租房屋裝修改造及租賃糾紛解決協(xié)議
- 2025年度區(qū)塊鏈技術(shù)應(yīng)用合伙投資合同
- 2025年度城市老舊建筑拆除勞務(wù)合作合同
- 2025年度教師聘用的教育教學(xué)改革與創(chuàng)新合同
- 親子樂園裝修合同樣板
- 中國古典文獻-第七章-文獻目錄
- 學(xué)前教育大專畢業(yè)論文3000字
- 注塑領(lǐng)班簡歷樣板
- 骨骼肌-人體解剖學(xué)-運動系統(tǒng)
- 基于康耐視相機的視覺識別實驗指導(dǎo)書
- 三年級書法下冊《第9課 斜鉤和臥鉤》教學(xué)設(shè)計
- 兒童財商養(yǎng)成教育講座PPT
- 大學(xué)學(xué)院學(xué)生獎助資金及相關(guān)經(jīng)費發(fā)放管理暫行辦法
- 2022蘇教版科學(xué)五年級下冊全冊優(yōu)質(zhì)教案教學(xué)設(shè)計
- 2023年R2移動式壓力容器充裝操作證考試題及答案(完整版)
- 九年級物理實驗記錄單
評論
0/150
提交評論