Spring基礎與實踐課件_第1頁
Spring基礎與實踐課件_第2頁
Spring基礎與實踐課件_第3頁
Spring基礎與實踐課件_第4頁
Spring基礎與實踐課件_第5頁
已閱讀5頁,還剩103頁未讀, 繼續(xù)免費閱讀

下載本文檔

版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領

文檔簡介

Spring

基礎與實踐

www.目的介紹Spring兩大核心技術--依賴注入(DI)和面向切面編程(AOP)。介紹Spring是如何利用這兩種技術來開發(fā)松散耦合的Java應用程序。SUNWAH目錄Spring介紹1依賴注入(DI)2面向切面編程(AOP)3實踐4SUNWAH

1.1Spring是什么Spring是一個基于JAVA語言、開源、輕量級的DI和AOP容器框架。EJB的聲明式編程模型確實簡化了很多基礎設施層面的開發(fā),如事務和安全,但在部署文件維護和各種接口(home、remote/local接口)實現等方面變得很復雜。很多新技術包括AOP和DI為JavaBeans提供了很多EJB才擁有的強大功能。這些技術使用EJB那樣的聲明式編碼模型來提供簡單潔凈Java對象(POJO)。負責輕量級POJO開發(fā)就是Spring框架。Spring框架是以簡化J2EE應用程序開發(fā)為特定目標而創(chuàng)建的。使用Spring,你可以用簡單的JavaBeans來實現那些以前只有EJB才能實現的功能。SUNWAH

Spring具有很多功能,可以將它們歸納為幾個基本部件。Spring是一個輕量級的DI和AOP容器框架。輕量級—從大小和應用開支上說Spring都算是輕量級的。整個Spring框架可以打成一個2.5MB多一點的JAR包,并且Spring的處理開支也非常小。更重要的是,Spring是非侵入式的:基于Spring開發(fā)的應用中的對象一般不依賴于Spring的類。依賴注入—Spring提供了一種松耦合的技術,稱為依賴注入(DI)。使用DI,對象是被動接受依賴類而不是自己主動去找。對象不是從容器中查找它的依賴類,而是容器在實例化對象的時候主動將它的依賴類注入給它。SUNWAH

面向切面—Spring對面向切面編程提供了強大支持,通過將業(yè)務邏輯從應用服務(如監(jiān)控和事務管理)中分離出來,實現了內聚開發(fā)。應用對象只做它們該做的——業(yè)務邏輯,它們不負責(或關心)其它系統(tǒng)問題(如日志和事務支持)。容器—Spring是一個容器,因為它包含并且管理應用對象的生命周期和配置。你可以通過配置來設定你的Bean是單一實例,還是每次請求產生一個實例,并且設定它們之間的關聯關系。Spring有別于傳統(tǒng)的重量級EJB容器,這些容器通常很大,很笨重??蚣堋猄pring實現了使用簡單的組件配置組合成一個復雜的應用。在Spring中,應用中的對象是通過XML文件配置組合起來的。并且Spring提供了很多基礎功能(事務管理、持久層集成等),這使開發(fā)人員能夠專注于開發(fā)應用邏輯。SUNWAH

核心容器Spring的最底層是核心容器。Spring核心容器為Spring框架提供了基礎功能。在這個模塊中你會找到BeanFactory這個類,它是最基本的Spring容器和Spring的DI所依賴的基礎。ApplicationContext(上下文)模塊

Spring的應用上下文建立在核心容器之上。如果說核心模塊中的BeanFactory使Spring成為容器的話,那么,上下文模塊就是使Spring成為框架的原因。這個模塊擴展BeanFactory,添加了對I18N(國際化)、應用生命周期事件以及驗證的支持。SUNWAH

Spring的AOP模塊

在AOP模塊中,Spring對面向切面編程提供了豐富的支持。這個模塊是為Spring應用開發(fā)切面的基礎。與DI一樣,AOP支持應用對象之間的松耦合。利用AOP,應用程序所關心的與其應用的對象關系不大。JDBC抽象及DAO模塊

編寫JDBC代碼時總是要寫一些樣板式的代碼,如:獲得連接、創(chuàng)建語句、處理結果、最后關閉連接。Spring的JDBC和DAO模塊把這些樣板式的代碼抽象出來,讓你的數據庫代碼變得簡單明了,也可以避免因為釋放數據庫資源失敗而引起的問題。這個模塊還建立了一個容易理解的數據庫異常層,它建立在各種數據庫錯誤信息之上。以后就不用再去解釋那些隱晦專有的SQL錯誤信息了。另外,這個模塊利用Spring的AOP模塊為Spring應用中的對象提供事務管理服務。

SUNWAH

ORM映射集成模塊JMX(Java管理擴展)JavaEE連接器API(JCA)SpringMVC框架SpringPortletMVCSpring的Web模塊遠程調用Java消息服務(JMS)SUNWAHHelloWorld程序代碼GreetingServiceImpl負責打印問候語。packagecom.sunwah.training.spring.hello;/**

*

Greeting

ServiceImpl負責打印問候語

*/public

classGreetingServiceImplimplementsGreetingService{//問候語privateStringgreeting;publicGreetingServiceImpl(){}SUNWAH

publicGreetingServiceImpl(Stringgreeting){this.greeting=greeting;}//打印問候語public

voidsayGreeting(){System.out.println(greeting);}public

voidsetGreeting(Stringgreeting){this.greeting=greeting;}}SUNWAHXML配置文件<?xml

version="1.0"

encoding="UTF-8"?><beans

xmlns=""xmlns:xsi=""xsi:schemaLocation=""><bean

id="greetingService"

class="com.sunwah.training.spring.hello.GreetingServiceImpl"><property

name="greeting"

value="HelloWorld!"

/></bean><bean

id="greetingService2"

class="com.sunwah.training.spring.hello.GreetingServiceImpl"><constructor-arg

value="HelloWorld!"

/></bean></beans>SUNWAH

執(zhí)行HelloWorld程序packagecom.sunwah.training.spring.hello;importorg.springframework.beans.factory.BeanFactory;importorg.springframework.beans.factory.xml.XmlBeanFactory;importorg.springframework.core.io.ClassPathResource;public

classHelloMain{public

static

voidmain(String[]args)throwsException{BeanFactoryfactory=newXmlBeanFactory(newClassPathResource("spring-hello.xml"));SUNWAH

//屬性注入GreetingServicegreetingService=(GreetingService)factory.getBean("greetingService");greetingService.sayGreeting();//構造注入GreetingServicegreetingService2=(GreetingService)factory.getBean("greetingService");greetingService2.sayGreeting();}}SUNWAH

這段代碼的用處就是載入Spring容器并且利用它得到問候服務。

這里用到的BeanFactory就是Spring容器。將spring-hello.xml文件載入容器后,main()方法調用BeanFactory的getBean()方法來得到問候服務的引用。使用這個引用,它最后調用了sayGreeting()方法。當我們運行HelloMain程序時,它在屏幕上打出“HelloWorld!”。

SUNWAH

在Spring中,組件無需自己負責與其他組件的關聯。取而代之的是,容器負責把協作組件的引用給予各個組件。創(chuàng)建系統(tǒng)組件之間協作關系的這個動作是DI的關鍵,通常被稱之為裝配。SUNWAH2.1容納你的Bean在基于Spring的應用中,應用組件在Spring范圍內是激活的。容器可以創(chuàng)建組件,裝配和配置組件,以及管理他們的整個生命周期(從new到finalize())。首先,要知道容器是組件存活的地方。容器是Spring框架的核心。Spring容器使用DI管理所有注冊應用系統(tǒng)的組件。包括在協作組件之間建立關聯。Spring提供了多種容器實現,并分為兩類。Bean工廠(由org.springframework.beans.factory.BeanFactory接口定義)是最簡單的容器,提供了基礎的依賴注入支持。應用上下文(由org.springframework.context.ApplicationContext接口定義)建立在Bean工廠基礎之上,提供了系統(tǒng)架構服務。SUNWAH2.1.1使用Bean工廠Bean工廠采用了工廠設計模式,這個類負責創(chuàng)建、分發(fā)各種類型的Bean及創(chuàng)建協作對象間的關聯關系。Bean工廠還要參與到Bean的生命周期中,調用用戶定義的初始化和銷毀方法。org.springframework.beans.factory.xml.XmlBeanFactory是最常使用的BeanFactory的實現,它根據XML文件中的定義裝載Bean。例:BeanFactoryfactory=newXmlBeanFactory(new("c:/beans.xml"));這段代碼的意思是告訴Bean工廠從XML文件中讀取Bean的定義信息。但是Bean只有在被需要的時候才被實例化。為了從BeanFactory中得到一個Bean,只要簡單調用getBean()方法。

例:

MyBeanmyBean=(MyBean)factory.getBean("myBean");

當getBean()方法被調用的時候,工廠就會實例化Bean并且使用依賴注入設置Bean的屬性。這樣就在Spring容器中開始了Bean的生命。SUNWAH

ApplicationContext與BeanFactory另一個重要區(qū)別是關于單例的Bean是如何被載入的:

BeanFactory延遲載入所有的Bean,直到getBean()方法被調用時Bean才被創(chuàng)建。應用上下文會在上下文啟動后預載入所有的單實例Bean。SUNWAH2.1.3Bean的生命

SUNWAH

SUNWAH

Bean在Spring應用上下文的生命周期與在Bean工廠中的生命周期只有一點不同:

如果Bean實現了ApplicationContextAware接口,setApplicationContext()方法會被調用。SUNWAH2.2創(chuàng)建Bean定義“表演者”接口:

packagecom.sunwah.training.spring.di;/**

*

表演者接口

*

*/public

interfacePerformer{/**

*

表演

*

@throws

PerformanceException

*/public

voidperform()throwsPerformanceException;}SUNWAH2.2.1聲明一個簡單的Bean定義“魔術師”類:

packagecom.sunwah.training.spring.di;/**

*魔術師類

*/public

classJugglerimplementsPerformer{ //小布袋 private

int

beanBags=3; publicJuggler(){ } publicJuggler(intbeanBags){ this.beanBags=beanBags; } public

voidperform()throwsPerformanceException{ System.out.println("JUGGLING"+beanBags+"BEANBAGS"); } public

voidsetBeanBags(intbeanBags){ this.beanBags=beanBags; }}SUNWAH

在Spring配置文件中聲明Bean:<bean

id="juggler"

class="com.sunwah.training.spring.di.Juggler"

/><bean>元素是Spring中最基本的配置單元,它通知Spring創(chuàng)建一個對象。Id屬性定義了該Bean的名稱,class屬性指明了它是個Juggler。當Spring容器裝載該Bean時,它將采用默認的構造函數來實例化jugglerBean。實際上是采用下面的java代碼來創(chuàng)建:newcom.sunwah.training.spring.di.Juggler();SUNWAH

使用以下代碼來裝載Spring應用上下文:ApplicationContextctx=newClassPathXmlApplicationContext("spring-di.xml");//默認屬性值Performerjuggler=(Performer)ctx.getBean("juggler");juggler.perform();SUNWAH2.2.2通過構造函數注入注入基本類型的值:<bean

id="juggler1"

class="com.sunwah.training.spring.di.Juggler"><constructor-arg

value="6"

/></bean>

注入其他對象SUNWAH

定義“詩歌”接口:

packagecom.sunwah.training.spring.di;/**

*

*

詩歌接口

*

*/public

interfacePoem{/**

*

朗誦

*/public

voidrecite();}SUNWAH

定義“作十四行詩”類:

packagecom.sunwah.training.spring.di;/**

*十四行詩類

*/public

classSonnet29implementsPoem{private

staticString[]LINES={"When,indisgracewithfortuneandmen'seyes,","Iallalonebeweepmyoutcaststate","Andtroubledeafheavenwithmybootlesscries","Andlookuponmyselfandcursemyfate,","Wishingmeliketoonemorerichinhope,","Featuredlikehim,likehimwithfriendspossess'd,","Desiringthisman'sartandthatman'sscope,","WithwhatImostenjoycontentedleast;","Yetinthesethoughtsmyselfalmostdespising,","HaplyIthinkonthee,andthenmystate,","Liketothelarkatbreakofdayarising","Fromsullenearth,singshymnsatheaven'sgate;","Forthysweetloveremember'dsuchwealthbrings","ThatthenIscorntochangemystatewithkings."};SUNWAH

publicSonnet29(){}/**

*

朗誦

*/public

voidrecite(){for(inti=0;i<LINES.length;i++){System.out.println(LINES[i]);}}}SUNWAH

定義“會誦詩的魔術師”類:

packagecom.sunwah.training.spring.di;/**

*會誦詩的魔術師

*/public

classPoeticJugglerextendsJuggler{//詩歌privatePoempoem;publicPoeticJuggler(){super();}publicPoeticJuggler(Poempoem){super();this.poem=poem;}SUNWAH

publicPoeticJuggler(intbeanBags,Poempoem){super(beanBags);this.poem=poem;}public

voidperform()throwsPerformanceException{super.perform();System.out.println("Whilereciting...");poem.recite();}public

voidsetPoem(Poempoem){this.poem=poem;}}SUNWAH

Sonnet29在Spring配置文件中的定義:: <bean

id="sonnet29"

class="com.sunwah.training.spring.di.Sonnet29"/>PoeticJuggler在Spring配置文件中的定義:<bean

id="poeticJuggler"

class="com.sunwah.training.spring.di.PoeticJuggler"><constructor-arg

value="12"

/><constructor-arg

ref="sonnet29"

/></bean>SUNWAH2.2.3通過setter方法注入通常Bean提供一對函數用來訪問屬性:setXXX()和getXXX()。Spring可以通過setter注入,利用setter方法來配置屬性值。Spring用setter方法把<property>元素里面設置的值注入到對象中。屬性name對應對象的屬性名稱,屬性value就是要注入的值。注入簡單的數值<bean

id="juggler2"

class="com.sunwah.training.spring.di.Juggler"><property

name="beanBags"

value="9"

/></bean>SUNWAH

注入其他的Bean<bean

id="poeticJuggler1"

class="com.sunwah.training.spring.di.PoeticJuggler"><property

name="beanBags"

value="15"

/><property

name="poem"

ref="sonnet29"

/></bean>SUNWAH2.2.4選擇構造函數注入還是Set注入?使用構造函數注入的優(yōu)點:

構造函數注入強制使用強依賴契約。如果沒有提供所有需要的依賴,一個Bean就無法被實例化。由于Bean的依賴都通過它的構造函數設置,所以沒有必要再寫多月的Set方法。這有助于減少代碼。因為只能通過構造函數設置類的屬性,這樣做能有效地保證了屬性的不可變性。使用構造函數注入的缺點:如果Bean有很多依賴,那么構造函數的參數列表會很長。如果一個對象已經有很多種構造方式,那么很難再提出不同的構造函數,因為構造函數只能通過參數的個數和類型來區(qū)分。?如果構造函數的參數中有兩個以上是相同類型的,那么很難確定每個參數的用途。? 構造函數注入不利于自身的繼承。Bean的構造函數為了給父類的私有變量賦值,需要把參數傳遞給super()方法。SUNWAH2.3裝配集合Spring提供了4個類型的集合配置元素:集合元素用途<list>裝配一列值,允許重復<set>裝配值集,不允許重復<map>裝配名稱-值對的集合,名稱和值可以是任意類型<props>裝配名稱-值對的集合,名稱和值都必須是String類型SUNWAH

<list>和<set>對應的屬性類型是array或者是java.util.Collection。<map>和<props>對應是java.util.Map和java.util.Properties。SUNWAH

使用<list>配置元素:<bean

id="hank"

class="com.springinaction.springidol.OneManBand"><property

name="instruments"><list><ref

bean="guitar"

/><ref

bean="cymbal"

/><ref

bean="harmonica"

/></list></property></bean>SUNWAH

使用<set>配置元素:<bean

id="hank"

class="com.springinaction.springidol.OneManBand"><property

name="instruments"><set><ref

bean="guitar"

/><ref

bean="cymbal"

/><ref

bean="harmonica"

/></set></property></bean>SUNWAH

使用<map>配置元素:<bean

id="hank"

class="com.springinaction.springidol.OneManBand"><property

name="instruments"><map><entry

key="GUITAR"

value-ref="guitar"

/><entry

key="CYMBAL"

value-ref="cymbal"

/><entry

key="HARMONICA"

value-ref="harmonica"

/></map></property></bean>SUNWAH

使用<props>配置元素:<bean

id="hank"

class="com.springinaction.springidol.OneManBand"><property

name="instruments"><props><prop

key="GUITAR">STRUMSTRUMSTRUM</prop><prop

key="CYMBAL">CRASHCRASHCRASH</prop><prop

key="HARMONICA">HUMHUMHUM</prop></props></property></bean>SUNWAH2.4自動裝配默認情況下,Bean不會自動裝配。有兩個辦法可以讓Spring自動裝配:設置需要自動裝配的<bean>中的autowire屬性。通過在Spring配置文件的根元素<beans>設置default-autowire屬性。Spring提供了四種自動裝配類型:byName—試圖在容器中尋找和需要自動裝配的屬性名相同的Bean(或ID)。如果沒有找到相符的Bean,這個屬性就沒有被裝配上。byType—試圖在容器中尋找一個與需要自動配置的屬性類型相同的Bean。如果沒有找到相符的Bean,這個屬性就沒有被裝配上。如果找到超過一個相符的Bean,就會拋出異常。constructor—試圖在容器中查找與需要自動裝配的Bean的構造函數參數一致的一個或多個Bean。如果存在不確定Bean或構造函數,容器會拋出異常。autodetect—首先嘗試使用constructor來自動裝配,然后使用byType方式。SUNWAH

可以混合使用自動和手動裝配。使用自動裝配雖然有利于減少編寫裝配文件,但是自動隱藏了很多細節(jié),缺乏透明,因此一般建議采用手動裝配。SUNWAH2.5控制Bean創(chuàng)建默認情況下,所有SpringBean都是單一的。為了使得每次都能產生一個新的Bean實例,可以聲明Bean的scope屬性為prototype。SUNWAH2.5.1Bean范圍化

Bean的范圍化選項主要有兩種:

singleton—單例,定義Bean的范圍為每個Spring容器一個實例(默認值)。prototype—原型,允許Bean可以被多次實例化(每次都創(chuàng)建一個新實例)。例如:<bean

id="saxophone"

class="com.springinaction.springidol.Saxophone"scope="prototype"

/>SUNWAH2.5.2利用工廠方法來創(chuàng)建Bean在Spring應用上下文中配置的Bean都可以通過調用類的構造函數來創(chuàng)建,也可以通過靜態(tài)工廠方法來創(chuàng)建。

<bean>元素有一個factory-method屬性,允許指定要調用的靜態(tài)方法,而不是使用構造函數內創(chuàng)建類的實例。

<bean

id="theStage"

class="com.springinaction.springidol.Stage"factory-method="getInstance"

/>SUNWAH2.5.3初始化和銷毀Bean<bean>元素中的init-method屬性指定了在Bean初始化是要調用的方法,destroy-method指定了將Bean從容器中刪除時要調用的方法。<bean

id="kenny"

class="com.springinaction.springidol.Instrumentalist"init-method="tuneInstrument"

destroy-method="cleanInstrument"><property

name="song"

value="JingleBells"/><property

name="instrument"

ref="saxophone"/></bean>SUNWAH默認的初始化和銷毀方法<beans>元素中的default-init-method屬性設置了一個上下文定義文件中所有Bean的初始化方法,default-destroy-method設置了上下文定義文件中所有Bean的銷毀方法。<?xml

version="1.0"

encoding="UTF-8"?><beans

xmlns=""xmlns:xsi=""xsi:schemaLocation=""default-init-method="tuneInstrument"

default-destroy-method="cleanInstrument">…</beans>SUNWAH2.6聲明父Bean和子Bean創(chuàng)建一個類來擴展另一個類是面向對象的基礎之一。在Java的類結構里,為了把通用的功能和屬性集中起來,可以把它們定義在父類里,讓子類來繼承。出于同樣的目的,我們從<bean>定義里擴展和繼承新的<bean>。這樣做還會有效地減少Spring上下文定義文件里冗余的XML。SUNWAH

為了實現Bean的繼承,<bean>元素提供了兩個特殊屬性:parent:指明Bean的id。它對于<bean>的作用相當于關鍵字extends對于Java類的作用。abstract:如果設置為true,就表示<bean>聲明是抽象的,不能被Spring實例化。SUNWAH2.6.1抽象基Bean類型定義兩個相同類型的Bean<bean

id="kenny"

class="com.springinaction.springidol.Instrumentalist"><property

name="song"

value="JingleBells"

/><property

name="instrument"

ref="saxophone"

/></bean><bean

id="david"

class="com.springinaction.springidol.Instrumentalist"><property

name="song"

value="JingleBells"

/><property

name="instrument"

ref="saxophone"

/></bean>SUNWAH

上面兩個Bean的定義可以采用繼承來實現:<bean

id="baseSaxophonist"

class="com.springinaction.springidol.Instrumentalist"abstract="true"><property

name="instrument"

ref="saxophone"

/><property

name="song"

value="JingleBells"

/></bean><bean

id="kenny"

parent="baseSaxophonist"

/><bean

id="david"

parent="baseSaxophonist"

/>SUNWAH

在父Bean定義中,abstract屬性設置為true,這就告訴Spring不要實例化這個Bean。父Bean不必一定是抽象的,從一個具體Bean也可以創(chuàng)建子Bean。在子Bean定義中,parent屬性表明kenny和david都繼承自baseSaxophonist。在子Bean定義中沒有class屬性,這是因為kenny和david不僅會繼承父Bean的屬性,也會繼承它的類型。子Bean可以覆蓋繼承的屬性。SUNWAH2.6.2抽象共同屬性以下兩個Bean有相同的屬性song,而且注入的屬性值也一樣。<bean

id="taylor"

class="com.springinaction.springidol.Vocalist"><property

name="song"

value="SomewhereOvertheRainbow"

/></bean><bean

id="stevie"

class="com.springinaction.springidol.Instrumentalist"><property

name="instrument"

ref="guitar"

/><property

name="song"

value="SomewhereOvertheRainbow"

/></bean>SUNWAH

抽象公共屬性:<bean

id="basePerformer"

abstract="true"><property

name="song"

value="SomewhereOvertheRainbow"

/></bean><bean

id="taylor"

class="com.springinaction.springidol.Vocalist"parent="basePerformer"

/><bean

id="stevie"

class="com.springinaction.springidol.Instrumentalist"parent="basePerformer"><property

name="instrument"

ref="guitar"

/></bean>SUNWAH

注意父beanbasePerformer沒有class屬性。這沒有問題,因為子Bean會利用自己的class屬性來確定自己的類型。SUNWAH2.7小結Spring框架的核心是Spring容器。Spring提供了多種實現容器的方法,這些方法可以歸納為兩類:BeanFactory是最簡單的容器,它提供了基本的DI和Bean裝配服務。如果需要用到更高級的框架服務,就需要使用Spring的ApplicationContext。在本課中,我們介紹了如何將Bean與Spring容器裝配在一起。通常,在Spring容器中使用XML來執(zhí)行裝配。這個XML文件包括了幫助容器執(zhí)行DI的信息,以便Bean能夠與其所依賴的其他Bean相關聯。SUNWAH3、面向切面編程(AOP)面向切面編程(AOP)SUNWAH

在軟件開發(fā)中,散布于程序中多個地點的函數被稱為“交叉事務”。從概念上來說,它們一般是與程序業(yè)務邏輯分開的(但經常是直接嵌入其中的)。把這些交叉事務與業(yè)務邏輯分離開正是面向切面編程(AOP)的作用所在。SUNWAH3.1

AOP簡介SUNWAH3.1.1定義AOP術語通知(Advice)切面的功能被稱為“通知”。通知定義了切面是什么以及何時使用。連接點(Joinpoint) 連接點是在程序執(zhí)行過程中能夠插入切面的一個點。這個點可以是方法被調用時、異常被拋出時、甚至字段被編輯時。切面代碼可以通過這些點插入到程序的一般流程之中,從而添加新的行為。SUNWAH

切入點(Pointcut) 一個切面不是一定要通知程序里全部的連接點。切入點可以縮小切面通知的連接點的范圍。如果說通知定義了切面的“什么”和“何時”,那么切入點就定義了“何地”。切入點的定義匹配通知要接入點一個或多個連接點。切面(Aspect) 切面是通知和切入點的結合。通知和切入點共同定義了關于切面的全部內容—它的功能、在何時和何地完成其功能。SUNWAH

引入(Introduction) “引入”允許我們向現有的類添加新方法和屬性。目標(Target) “目標”是被通知的對象。代理(Proxy) “代理”是向目標對象應用通知之后被創(chuàng)建的對象。織入(Weaving) “織入”是把切面應用到目標對象來創(chuàng)建新的代理對象的過程。切面在指定連接點織入到目標對象。SUNWAH

織入的時機:? 編譯時:切面在目標類編譯時被織入。? 類加載時:切面在目標類加載到JVM時被織入。? 運行時:切面在程序運行時的某個時刻被織入。

SUNWAH3.1.2Spring對AOP的支持創(chuàng)建切點來定義切面織入的連接點是AOP框架的基本功能。Spring對AOP的支持具有以下4種情況: ?經典的基于代理的AOP?@AspectJ注解驅動的切面?純POJO切面?注入式AspectJ切面 前三種都是基于代理的AOP的變體,因此,Spring對于AOP的支持局限于方法注入。SUNWAH

Spring的AOP框架的幾個關鍵點:Spring通知是用JAVA編寫的。 Spring創(chuàng)建的全部通知都是用標準JAVA類編寫的。定義通知所應用的切點通常是以XML方式寫在Spring配置文件里。Spring在運行時通知對象。 Spring利用代理類包裹切面,從而把它們織入到Spring管理的Bean里。代理類裝作目標Bean,截取被通知的方法調用,再把這些調用轉發(fā)到真正的目標Bean。在代理截取方法調用之后,實際調用目標Bean的方法之前,代理會執(zhí)行切面邏輯。Spring只支持方法連接點。由于Spring是基于動態(tài)代理的,它只支持方法連接點。SUNWAH3.2創(chuàng)建經典的Spring切面定義一個觀眾類:packagecom.sunwah.training.spring.aop;importorg.aspectj.lang.ProceedingJoinPoint;/**

*

觀眾

*

*/public

classAudience{publicAudience(){}public

voidwatchPerformance(ProceedingJoinPointjp){System.out.println("Theaudienceistakingtheirseats.");System.out.println("Theaudienceisturningofftheircellphones");try{ceed();System.out.println("CLAPCLAPCLAPCLAPCLAP");}catch(Throwablethrowable){System.out.println("Boo!Wewantourmoneyback!");}}SUNWAH

//落座public

voidtakeSeats(){System.out.println("Theaudienceistakingtheirseats.");}//關閉自己的手機public

voidturnOffCellPhones(){System.out.println("Theaudienceisturningofftheircellphones");}//鼓掌public

voidapplaud(){System.out.println("CLAPCLAPCLAPCLAPCLAP");}//退票public

voiddemandRefund(){System.out.println("Boo!Wewantourmoneyback!");}}SUNWAH

使用如下XML可以把它裝配為Spring的<bean>:<!--觀眾--><bean

id="audience"

class="com.sunwah.training.spring.aop.Audience"

/>SUNWAH3.2.1創(chuàng)建通知Spring的AOP里有5種類型的通知,分別由一個接口進行定義:通知類型接口Before(前)org.springframework.aop.MethodBeforeAdviceAfter-returning(返回后)org.springframework.aop.AfterReturningAdviceAfter-throwing(拋出后)org.springframework.aop.ThrowsAdviceAround(周圍)ercept.MethodInterceptorIntroduction(引入)org.springframework.aop.IntroductionInterceptorSUNWAH前通知、返回后通知和拋出后通知定義觀眾功能如何被使用的通知:packagecom.sunwah.training.spring.aop;importjava.lang.reflect.Method;importorg.springframework.aop.AfterReturningAdvice;importorg.springframework.aop.MethodBeforeAdvice;importorg.springframework.aop.ThrowsAdvice;/**

*

*

定義觀眾功能如何被使用的通知(實現了三種類型的通知)

*

*/public

classAudienceAdviceimplementsMethodBeforeAdvice,AfterReturningAdvice,ThrowsAdvice{publicAudienceAdvice(){}SUNWAH

//在方法之前調用public

voidbefore(Methodmethod,Object[]args,Objecttarget)throwsThrowable{audience.takeSeats();audience.turnOffCellPhones();}//在成功返回之后調用public

voidafterReturning(Objectrtn,Methodmethod,Object[]args,Objecttarget)throwsThrowable{audience.applaud();}//在拋出異常之后執(zhí)行public

voidafterThrowing(Throwablethrowable){audience.demandRefund();}SUNWAH

//在拋出異常之后執(zhí)行public

voidafterThrowing(Methodmethod,Object[]args,Objecttarget,Throwablethrowable){audience.demandRefund();}//injectedprivateAudienceaudience;public

voidsetAudience(Audienceaudience){this.audience=audience;}}SUNWAH

XML配置文件如下:<!--前通知、返回后通知和拋出后通知--><bean

id="audienceAdvice"

class="com.sunwah.training.spring.aop.AudienceAdvice"><property

name="audience"

ref="audience"

/></bean>SUNWAH周圍通知周圍通知相當于前通知、返回后通知、拋出后通知的結合。在Spring里,周圍通知是由AOPAlliance的MethodInterceptor接口定義的。編寫周圍通知的好處:

?能以簡潔的方式在一個方法里定義前通知和后通知。

?可以檢查和修改被通知方法的返回值。

SUNWAH

以周圍通知方式定義觀眾通知:packagecom.sunwah.training.spring.aop;importercept.MethodInterceptor;importercept.MethodInvocation;importcom.sunwah.training.spring.di.PerformanceException;/**

*

*

以周圍通知方式定義觀眾通知

*

*/public

classAudienceAroundAdviceimplementsMethodInterceptor{SUNWAH

publicObjectinvoke(MethodInvocationinvocation)throwsThrowable{try{//在方法調用前執(zhí)行audience.takeSeats();audience.turnOffCellPhones();//調用目標方法ObjectreturnValue=ceed();//在成功返回之后執(zhí)行audience.applaud();returnreturnValue;}catch(PerformanceExceptionthrowable){//出現異常之后執(zhí)行audience.demandRefund();throwthrowable;}}SUNWAH

//injectedprivateAudienceaudience;public

voidsetAudience(Audienceaudience){this.audience=audience;}}SUNWAH3.2.2定義切點和通知者連接點就是程序代碼里切面通知可以被織入的地點。切點是以某種方式選擇全部連接點的一個子集來定義通知應該被織入的地點。

SUNWAH聲明正則表達式切點定義切點:<bean

id="performancePointcut"

class="org.springframework.aop.support.JdkRegexpMethodPointcut"><property

name="pattern"

value=".*perform"

/></bean>類JdkRegexpMethodPointcut實現正則表達式切點。pattern屬性用于指定方法匹配所使用的切點模板。

SUNWAH

將切點與通知相關聯:<bean

id="audienceAdvisor"

class="org.springframework.aop.support.DefaultPointcutAdvisor"><property

name="advice"

ref="audienceAdvice"

/><property

name="pointcut"

ref="performancePointcut"

/></bean>DefaultPointcutAdvisor類是個通知者類,它只是把通知關聯到一個切點。

SUNWAH

聯合切點與通知者:<bean

id="audienceAdvisor"class="org.springframework.aop.support.RegexpMethodPointcutAdvisor"><property

name="advice"

ref="audienceAdvice"

/><property

name="pattern"

value=".*perform"

/></bean>RegexpMethodPointcutAdvisor是個特殊的通知者類,可以在一個Bean里定義切點和通知者。

SUNWAH聲明AspectJ切點定義切點:<bean

id="performancePointcut"class="org.springframework.aop.aspectj.AspectJExpressionPointcut"><property

name="expression"

value="execution(**.perform(..))"

/></bean>這里使用AspectJExpressionPointcut類而不是JdkRegexpMethodPointcut類。切點表達是被定義為expression屬性的值。

SUNWAH

將切點與通知相關聯:<bean

id="audienceAdvisor"

class="org.springframework.aop.support.DefaultPointcutAdvisor"><property

name="advice"

ref="audienceAdvice"

/><property

name="pointcut"

ref="performancePointcut"

/></bean>DefaultPointcutAdvisor類是個通知者類,它只是把通知關聯到一個切點。

SUNWAH

聯合切點與通知者:<bean

id="audienceAdvisor"class="org.springframework.aop.aspectj.AspectJExpressionPointcutAdvisor"><property

name="advice"

ref="audienceAdvice"

/><property

name="expression"

value="execution(**.perform(..))"

/></bean>AspectJExpressionPointcutAdvisor是個通知者類,用來同時定義切點和通知者。

SUNWAH3.2.3使用ProxyFactoryBean作為被通知者通知的Bean,它必須是被代理的。Spring的ProxyFactoryBean是個工廠Bean,用于生成一個代理,把一個或多個(通知)應用到Bean。target屬性指明哪個Bean被代理;interceptorNames屬性指明哪些通知者要應用于被代理的Bean;proxyInterfaces屬性指明代理應該實現哪些接口。

SUNWAH

定義演出者Duke的目標Bean:<!--定義演出者Duke目標Bean--><bean

id="dukeTarget"

class="com.sunwah.training.spring.di.PoeticJuggler"><property

name="beanBags"

value="15"

/><property

name="poem"

ref="sonnet29"

/></bean>SUNWAH

定義演出者Duke的代理Bean:<!--定義演出者Duke代理Bean--><bean

id="duke"

class="org.springframework.aop.framework.ProxyFactoryBean"><property

name="target"

ref="dukeTarget"

/><!--<propertyname="interceptorNames"value="audienceAdvisor"/>--><property

name="interceptorNames"><list><value>audienceAdvisor</value></list></property><property

SUNWAH抽象ProxyFactoryBean定義觀眾參與演出者Steive的演出:<!--定義演出者Stevie目標Bean--><bean

id="stevieTarget"

class="com.sunwah.training.spring.di.PoeticJuggler"><property

name="beanBags"

value="18"

/><property

name="poem"

ref="sonnet29"

/></bean>SUNWAH

<!--定義演出者Stevie代理Bean--><bean

id="stevie"

class="org.springframework.aop.framework.ProxyFactoryBean"><property

name="target"

ref="stevieTarget"/><!--<propertyname="interceptorNames"value="audienceAdvisor"/>--><property

name="interceptorNames"><list><value>audienceAdvisor<

溫馨提示

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

評論

0/150

提交評論