版權(quán)說(shuō)明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡(jiǎn)介
Spring
基礎(chǔ)與實(shí)踐
www.目的介紹Spring兩大核心技術(shù)--依賴注入(DI)和面向切面編程(AOP)。介紹Spring是如何利用這兩種技術(shù)來(lái)開(kāi)發(fā)松散耦合的Java應(yīng)用程序。SUNWAH目錄Spring介紹1依賴注入(DI)2面向切面編程(AOP)3實(shí)踐4SUNWAH
1.1Spring是什么Spring是一個(gè)基于JAVA語(yǔ)言、開(kāi)源、輕量級(jí)的DI和AOP容器框架。EJB的聲明式編程模型確實(shí)簡(jiǎn)化了很多基礎(chǔ)設(shè)施層面的開(kāi)發(fā),如事務(wù)和安全,但在部署文件維護(hù)和各種接口(home、remote/local接口)實(shí)現(xiàn)等方面變得很復(fù)雜。很多新技術(shù)包括AOP和DI為JavaBeans提供了很多EJB才擁有的強(qiáng)大功能。這些技術(shù)使用EJB那樣的聲明式編碼模型來(lái)提供簡(jiǎn)單潔凈Java對(duì)象(POJO)。負(fù)責(zé)輕量級(jí)POJO開(kāi)發(fā)就是Spring框架。Spring框架是以簡(jiǎn)化J2EE應(yīng)用程序開(kāi)發(fā)為特定目標(biāo)而創(chuàng)建的。使用Spring,你可以用簡(jiǎn)單的JavaBeans來(lái)實(shí)現(xiàn)那些以前只有EJB才能實(shí)現(xiàn)的功能。SUNWAH
Spring具有很多功能,可以將它們歸納為幾個(gè)基本部件。Spring是一個(gè)輕量級(jí)的DI和AOP容器框架。輕量級(jí)—從大小和應(yīng)用開(kāi)支上說(shuō)Spring都算是輕量級(jí)的。整個(gè)Spring框架可以打成一個(gè)2.5MB多一點(diǎn)的JAR包,并且Spring的處理開(kāi)支也非常小。更重要的是,Spring是非侵入式的:基于Spring開(kāi)發(fā)的應(yīng)用中的對(duì)象一般不依賴于Spring的類。依賴注入—Spring提供了一種松耦合的技術(shù),稱為依賴注入(DI)。使用DI,對(duì)象是被動(dòng)接受依賴類而不是自己主動(dòng)去找。對(duì)象不是從容器中查找它的依賴類,而是容器在實(shí)例化對(duì)象的時(shí)候主動(dòng)將它的依賴類注入給它。SUNWAH
面向切面—Spring對(duì)面向切面編程提供了強(qiáng)大支持,通過(guò)將業(yè)務(wù)邏輯從應(yīng)用服務(wù)(如監(jiān)控和事務(wù)管理)中分離出來(lái),實(shí)現(xiàn)了內(nèi)聚開(kāi)發(fā)。應(yīng)用對(duì)象只做它們?cè)撟龅摹獦I(yè)務(wù)邏輯,它們不負(fù)責(zé)(或關(guān)心)其它系統(tǒng)問(wèn)題(如日志和事務(wù)支持)。容器—Spring是一個(gè)容器,因?yàn)樗⑶夜芾響?yīng)用對(duì)象的生命周期和配置。你可以通過(guò)配置來(lái)設(shè)定你的Bean是單一實(shí)例,還是每次請(qǐng)求產(chǎn)生一個(gè)實(shí)例,并且設(shè)定它們之間的關(guān)聯(lián)關(guān)系。Spring有別于傳統(tǒng)的重量級(jí)EJB容器,這些容器通常很大,很笨重。框架—Spring實(shí)現(xiàn)了使用簡(jiǎn)單的組件配置組合成一個(gè)復(fù)雜的應(yīng)用。在Spring中,應(yīng)用中的對(duì)象是通過(guò)XML文件配置組合起來(lái)的。并且Spring提供了很多基礎(chǔ)功能(事務(wù)管理、持久層集成等),這使開(kāi)發(fā)人員能夠?qū)W⒂陂_(kāi)發(fā)應(yīng)用邏輯。SUNWAH
核心容器Spring的最底層是核心容器。Spring核心容器為Spring框架提供了基礎(chǔ)功能。在這個(gè)模塊中你會(huì)找到BeanFactory這個(gè)類,它是最基本的Spring容器和Spring的DI所依賴的基礎(chǔ)。ApplicationContext(上下文)模塊
Spring的應(yīng)用上下文建立在核心容器之上。如果說(shuō)核心模塊中的BeanFactory使Spring成為容器的話,那么,上下文模塊就是使Spring成為框架的原因。這個(gè)模塊擴(kuò)展BeanFactory,添加了對(duì)I18N(國(guó)際化)、應(yīng)用生命周期事件以及驗(yàn)證的支持。SUNWAH
Spring的AOP模塊
在AOP模塊中,Spring對(duì)面向切面編程提供了豐富的支持。這個(gè)模塊是為Spring應(yīng)用開(kāi)發(fā)切面的基礎(chǔ)。與DI一樣,AOP支持應(yīng)用對(duì)象之間的松耦合。利用AOP,應(yīng)用程序所關(guān)心的與其應(yīng)用的對(duì)象關(guān)系不大。JDBC抽象及DAO模塊
編寫(xiě)JDBC代碼時(shí)總是要寫(xiě)一些樣板式的代碼,如:獲得連接、創(chuàng)建語(yǔ)句、處理結(jié)果、最后關(guān)閉連接。Spring的JDBC和DAO模塊把這些樣板式的代碼抽象出來(lái),讓你的數(shù)據(jù)庫(kù)代碼變得簡(jiǎn)單明了,也可以避免因?yàn)獒尫艛?shù)據(jù)庫(kù)資源失敗而引起的問(wèn)題。這個(gè)模塊還建立了一個(gè)容易理解的數(shù)據(jù)庫(kù)異常層,它建立在各種數(shù)據(jù)庫(kù)錯(cuò)誤信息之上。以后就不用再去解釋那些隱晦專有的SQL錯(cuò)誤信息了。另外,這個(gè)模塊利用Spring的AOP模塊為Spring應(yīng)用中的對(duì)象提供事務(wù)管理服務(wù)。
SUNWAH
ORM映射集成模塊JMX(Java管理擴(kuò)展)JavaEE連接器API(JCA)SpringMVC框架SpringPortletMVCSpring的Web模塊遠(yuǎn)程調(diào)用Java消息服務(wù)(JMS)SUNWAHHelloWorld程序代碼GreetingServiceImpl負(fù)責(zé)打印問(wèn)候語(yǔ)。packagecom.sunwah.training.spring.hello;/**
*
Greeting
ServiceImpl負(fù)責(zé)打印問(wèn)候語(yǔ)
*/public
classGreetingServiceImplimplementsGreetingService{//問(wèn)候語(yǔ)privateStringgreeting;publicGreetingServiceImpl(){}SUNWAH
publicGreetingServiceImpl(Stringgreeting){this.greeting=greeting;}//打印問(wèn)候語(yǔ)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();//構(gòu)造注入GreetingServicegreetingService2=(GreetingService)factory.getBean("greetingService");greetingService2.sayGreeting();}}SUNWAH
這段代碼的用處就是載入Spring容器并且利用它得到問(wèn)候服務(wù)。
這里用到的BeanFactory就是Spring容器。將spring-hello.xml文件載入容器后,main()方法調(diào)用BeanFactory的getBean()方法來(lái)得到問(wèn)候服務(wù)的引用。使用這個(gè)引用,它最后調(diào)用了sayGreeting()方法。當(dāng)我們運(yùn)行HelloMain程序時(shí),它在屏幕上打出“HelloWorld!”。
SUNWAH
在Spring中,組件無(wú)需自己負(fù)責(zé)與其他組件的關(guān)聯(lián)。取而代之的是,容器負(fù)責(zé)把協(xié)作組件的引用給予各個(gè)組件。創(chuàng)建系統(tǒng)組件之間協(xié)作關(guān)系的這個(gè)動(dòng)作是DI的關(guān)鍵,通常被稱之為裝配。SUNWAH2.1容納你的Bean在基于Spring的應(yīng)用中,應(yīng)用組件在Spring范圍內(nèi)是激活的。容器可以創(chuàng)建組件,裝配和配置組件,以及管理他們的整個(gè)生命周期(從new到finalize())。首先,要知道容器是組件存活的地方。容器是Spring框架的核心。Spring容器使用DI管理所有注冊(cè)應(yīng)用系統(tǒng)的組件。包括在協(xié)作組件之間建立關(guān)聯(lián)。Spring提供了多種容器實(shí)現(xiàn),并分為兩類。Bean工廠(由org.springframework.beans.factory.BeanFactory接口定義)是最簡(jiǎn)單的容器,提供了基礎(chǔ)的依賴注入支持。應(yīng)用上下文(由org.springframework.context.ApplicationContext接口定義)建立在Bean工廠基礎(chǔ)之上,提供了系統(tǒng)架構(gòu)服務(wù)。SUNWAH2.1.1使用Bean工廠Bean工廠采用了工廠設(shè)計(jì)模式,這個(gè)類負(fù)責(zé)創(chuàng)建、分發(fā)各種類型的Bean及創(chuàng)建協(xié)作對(duì)象間的關(guān)聯(lián)關(guān)系。Bean工廠還要參與到Bean的生命周期中,調(diào)用用戶定義的初始化和銷毀方法。org.springframework.beans.factory.xml.XmlBeanFactory是最常使用的BeanFactory的實(shí)現(xiàn),它根據(jù)XML文件中的定義裝載Bean。例:BeanFactoryfactory=newXmlBeanFactory(new("c:/beans.xml"));這段代碼的意思是告訴Bean工廠從XML文件中讀取Bean的定義信息。但是Bean只有在被需要的時(shí)候才被實(shí)例化。為了從BeanFactory中得到一個(gè)Bean,只要簡(jiǎn)單調(diào)用getBean()方法。
例:
MyBeanmyBean=(MyBean)factory.getBean("myBean");
當(dāng)getBean()方法被調(diào)用的時(shí)候,工廠就會(huì)實(shí)例化Bean并且使用依賴注入設(shè)置Bean的屬性。這樣就在Spring容器中開(kāi)始了Bean的生命。SUNWAH
ApplicationContext與BeanFactory另一個(gè)重要區(qū)別是關(guān)于單例的Bean是如何被載入的:
BeanFactory延遲載入所有的Bean,直到getBean()方法被調(diào)用時(shí)Bean才被創(chuàng)建。應(yīng)用上下文會(huì)在上下文啟動(dòng)后預(yù)載入所有的單實(shí)例Bean。SUNWAH2.1.3Bean的生命
SUNWAH
SUNWAH
Bean在Spring應(yīng)用上下文的生命周期與在Bean工廠中的生命周期只有一點(diǎn)不同:
如果Bean實(shí)現(xiàn)了ApplicationContextAware接口,setApplicationContext()方法會(huì)被調(diào)用。SUNWAH2.2創(chuàng)建Bean定義“表演者”接口:
packagecom.sunwah.training.spring.di;/**
*
表演者接口
*
*/public
interfacePerformer{/**
*
表演
*
@throws
PerformanceException
*/public
voidperform()throwsPerformanceException;}SUNWAH2.2.1聲明一個(gè)簡(jiǎn)單的Bean定義“魔術(shù)師”類:
packagecom.sunwah.training.spring.di;/**
*魔術(shù)師類
*/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)建一個(gè)對(duì)象。Id屬性定義了該Bean的名稱,class屬性指明了它是個(gè)Juggler。當(dāng)Spring容器裝載該Bean時(shí),它將采用默認(rèn)的構(gòu)造函數(shù)來(lái)實(shí)例化jugglerBean。實(shí)際上是采用下面的java代碼來(lái)創(chuàng)建:newcom.sunwah.training.spring.di.Juggler();SUNWAH
使用以下代碼來(lái)裝載Spring應(yīng)用上下文:ApplicationContextctx=newClassPathXmlApplicationContext("spring-di.xml");//默認(rèn)屬性值Performerjuggler=(Performer)ctx.getBean("juggler");juggler.perform();SUNWAH2.2.2通過(guò)構(gòu)造函數(shù)注入注入基本類型的值:<bean
id="juggler1"
class="com.sunwah.training.spring.di.Juggler"><constructor-arg
value="6"
/></bean>
注入其他對(duì)象SUNWAH
定義“詩(shī)歌”接口:
packagecom.sunwah.training.spring.di;/**
*
*
詩(shī)歌接口
*
*/public
interfacePoem{/**
*
朗誦
*/public
voidrecite();}SUNWAH
定義“作十四行詩(shī)”類:
packagecom.sunwah.training.spring.di;/**
*十四行詩(shī)類
*/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
定義“會(huì)誦詩(shī)的魔術(shù)師”類:
packagecom.sunwah.training.spring.di;/**
*會(huì)誦詩(shī)的魔術(shù)師
*/public
classPoeticJugglerextendsJuggler{//詩(shī)歌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通過(guò)setter方法注入通常Bean提供一對(duì)函數(shù)用來(lái)訪問(wèn)屬性:setXXX()和getXXX()。Spring可以通過(guò)setter注入,利用setter方法來(lái)配置屬性值。Spring用setter方法把<property>元素里面設(shè)置的值注入到對(duì)象中。屬性name對(duì)應(yīng)對(duì)象的屬性名稱,屬性value就是要注入的值。注入簡(jiǎn)單的數(shù)值<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選擇構(gòu)造函數(shù)注入還是Set注入?使用構(gòu)造函數(shù)注入的優(yōu)點(diǎn):
構(gòu)造函數(shù)注入強(qiáng)制使用強(qiáng)依賴契約。如果沒(méi)有提供所有需要的依賴,一個(gè)Bean就無(wú)法被實(shí)例化。由于Bean的依賴都通過(guò)它的構(gòu)造函數(shù)設(shè)置,所以沒(méi)有必要再寫(xiě)多月的Set方法。這有助于減少代碼。因?yàn)橹荒芡ㄟ^(guò)構(gòu)造函數(shù)設(shè)置類的屬性,這樣做能有效地保證了屬性的不可變性。使用構(gòu)造函數(shù)注入的缺點(diǎn):如果Bean有很多依賴,那么構(gòu)造函數(shù)的參數(shù)列表會(huì)很長(zhǎng)。如果一個(gè)對(duì)象已經(jīng)有很多種構(gòu)造方式,那么很難再提出不同的構(gòu)造函數(shù),因?yàn)闃?gòu)造函數(shù)只能通過(guò)參數(shù)的個(gè)數(shù)和類型來(lái)區(qū)分。?如果構(gòu)造函數(shù)的參數(shù)中有兩個(gè)以上是相同類型的,那么很難確定每個(gè)參數(shù)的用途。? 構(gòu)造函數(shù)注入不利于自身的繼承。Bean的構(gòu)造函數(shù)為了給父類的私有變量賦值,需要把參數(shù)傳遞給super()方法。SUNWAH2.3裝配集合Spring提供了4個(gè)類型的集合配置元素:集合元素用途<list>裝配一列值,允許重復(fù)<set>裝配值集,不允許重復(fù)<map>裝配名稱-值對(duì)的集合,名稱和值可以是任意類型<props>裝配名稱-值對(duì)的集合,名稱和值都必須是String類型SUNWAH
<list>和<set>對(duì)應(yīng)的屬性類型是array或者是java.util.Collection。<map>和<props>對(duì)應(yīng)是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自動(dòng)裝配默認(rèn)情況下,Bean不會(huì)自動(dòng)裝配。有兩個(gè)辦法可以讓Spring自動(dòng)裝配:設(shè)置需要自動(dòng)裝配的<bean>中的autowire屬性。通過(guò)在Spring配置文件的根元素<beans>設(shè)置default-autowire屬性。Spring提供了四種自動(dòng)裝配類型:byName—試圖在容器中尋找和需要自動(dòng)裝配的屬性名相同的Bean(或ID)。如果沒(méi)有找到相符的Bean,這個(gè)屬性就沒(méi)有被裝配上。byType—試圖在容器中尋找一個(gè)與需要自動(dòng)配置的屬性類型相同的Bean。如果沒(méi)有找到相符的Bean,這個(gè)屬性就沒(méi)有被裝配上。如果找到超過(guò)一個(gè)相符的Bean,就會(huì)拋出異常。constructor—試圖在容器中查找與需要自動(dòng)裝配的Bean的構(gòu)造函數(shù)參數(shù)一致的一個(gè)或多個(gè)Bean。如果存在不確定Bean或構(gòu)造函數(shù),容器會(huì)拋出異常。autodetect—首先嘗試使用constructor來(lái)自動(dòng)裝配,然后使用byType方式。SUNWAH
可以混合使用自動(dòng)和手動(dòng)裝配。使用自動(dòng)裝配雖然有利于減少編寫(xiě)裝配文件,但是自動(dòng)隱藏了很多細(xì)節(jié),缺乏透明,因此一般建議采用手動(dòng)裝配。SUNWAH2.5控制Bean創(chuàng)建默認(rèn)情況下,所有SpringBean都是單一的。為了使得每次都能產(chǎn)生一個(gè)新的Bean實(shí)例,可以聲明Bean的scope屬性為prototype。SUNWAH2.5.1Bean范圍化
Bean的范圍化選項(xiàng)主要有兩種:
singleton—單例,定義Bean的范圍為每個(gè)Spring容器一個(gè)實(shí)例(默認(rèn)值)。prototype—原型,允許Bean可以被多次實(shí)例化(每次都創(chuàng)建一個(gè)新實(shí)例)。例如:<bean
id="saxophone"
class="com.springinaction.springidol.Saxophone"scope="prototype"
/>SUNWAH2.5.2利用工廠方法來(lái)創(chuàng)建Bean在Spring應(yīng)用上下文中配置的Bean都可以通過(guò)調(diào)用類的構(gòu)造函數(shù)來(lái)創(chuàng)建,也可以通過(guò)靜態(tài)工廠方法來(lái)創(chuàng)建。
<bean>元素有一個(gè)factory-method屬性,允許指定要調(diào)用的靜態(tài)方法,而不是使用構(gòu)造函數(shù)內(nèi)創(chuàng)建類的實(shí)例。
<bean
id="theStage"
class="com.springinaction.springidol.Stage"factory-method="getInstance"
/>SUNWAH2.5.3初始化和銷毀Bean<bean>元素中的init-method屬性指定了在Bean初始化是要調(diào)用的方法,destroy-method指定了將Bean從容器中刪除時(shí)要調(diào)用的方法。<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默認(rèn)的初始化和銷毀方法<beans>元素中的default-init-method屬性設(shè)置了一個(gè)上下文定義文件中所有Bean的初始化方法,default-destroy-method設(shè)置了上下文定義文件中所有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)建一個(gè)類來(lái)擴(kuò)展另一個(gè)類是面向?qū)ο蟮幕A(chǔ)之一。在Java的類結(jié)構(gòu)里,為了把通用的功能和屬性集中起來(lái),可以把它們定義在父類里,讓子類來(lái)繼承。出于同樣的目的,我們從<bean>定義里擴(kuò)展和繼承新的<bean>。這樣做還會(huì)有效地減少Spring上下文定義文件里冗余的XML。SUNWAH
為了實(shí)現(xiàn)Bean的繼承,<bean>元素提供了兩個(gè)特殊屬性:parent:指明Bean的id。它對(duì)于<bean>的作用相當(dāng)于關(guān)鍵字extends對(duì)于Java類的作用。abstract:如果設(shè)置為true,就表示<bean>聲明是抽象的,不能被Spring實(shí)例化。SUNWAH2.6.1抽象基Bean類型定義兩個(gè)相同類型的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
上面兩個(gè)Bean的定義可以采用繼承來(lái)實(shí)現(xiàn):<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屬性設(shè)置為true,這就告訴Spring不要實(shí)例化這個(gè)Bean。父Bean不必一定是抽象的,從一個(gè)具體Bean也可以創(chuàng)建子Bean。在子Bean定義中,parent屬性表明kenny和david都繼承自baseSaxophonist。在子Bean定義中沒(méi)有class屬性,這是因?yàn)閗enny和david不僅會(huì)繼承父Bean的屬性,也會(huì)繼承它的類型。子Bean可以覆蓋繼承的屬性。SUNWAH2.6.2抽象共同屬性以下兩個(gè)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沒(méi)有class屬性。這沒(méi)有問(wèn)題,因?yàn)樽覤ean會(huì)利用自己的class屬性來(lái)確定自己的類型。SUNWAH2.7小結(jié)Spring框架的核心是Spring容器。Spring提供了多種實(shí)現(xiàn)容器的方法,這些方法可以歸納為兩類:BeanFactory是最簡(jiǎn)單的容器,它提供了基本的DI和Bean裝配服務(wù)。如果需要用到更高級(jí)的框架服務(wù),就需要使用Spring的ApplicationContext。在本課中,我們介紹了如何將Bean與Spring容器裝配在一起。通常,在Spring容器中使用XML來(lái)執(zhí)行裝配。這個(gè)XML文件包括了幫助容器執(zhí)行DI的信息,以便Bean能夠與其所依賴的其他Bean相關(guān)聯(lián)。SUNWAH3、面向切面編程(AOP)面向切面編程(AOP)SUNWAH
在軟件開(kāi)發(fā)中,散布于程序中多個(gè)地點(diǎn)的函數(shù)被稱為“交叉事務(wù)”。從概念上來(lái)說(shuō),它們一般是與程序業(yè)務(wù)邏輯分開(kāi)的(但經(jīng)常是直接嵌入其中的)。把這些交叉事務(wù)與業(yè)務(wù)邏輯分離開(kāi)正是面向切面編程(AOP)的作用所在。SUNWAH3.1
AOP簡(jiǎn)介SUNWAH3.1.1定義AOP術(shù)語(yǔ)通知(Advice)切面的功能被稱為“通知”。通知定義了切面是什么以及何時(shí)使用。連接點(diǎn)(Joinpoint) 連接點(diǎn)是在程序執(zhí)行過(guò)程中能夠插入切面的一個(gè)點(diǎn)。這個(gè)點(diǎn)可以是方法被調(diào)用時(shí)、異常被拋出時(shí)、甚至字段被編輯時(shí)。切面代碼可以通過(guò)這些點(diǎn)插入到程序的一般流程之中,從而添加新的行為。SUNWAH
切入點(diǎn)(Pointcut) 一個(gè)切面不是一定要通知程序里全部的連接點(diǎn)。切入點(diǎn)可以縮小切面通知的連接點(diǎn)的范圍。如果說(shuō)通知定義了切面的“什么”和“何時(shí)”,那么切入點(diǎn)就定義了“何地”。切入點(diǎn)的定義匹配通知要接入點(diǎn)一個(gè)或多個(gè)連接點(diǎn)。切面(Aspect) 切面是通知和切入點(diǎn)的結(jié)合。通知和切入點(diǎn)共同定義了關(guān)于切面的全部?jī)?nèi)容—它的功能、在何時(shí)和何地完成其功能。SUNWAH
引入(Introduction) “引入”允許我們向現(xiàn)有的類添加新方法和屬性。目標(biāo)(Target) “目標(biāo)”是被通知的對(duì)象。代理(Proxy) “代理”是向目標(biāo)對(duì)象應(yīng)用通知之后被創(chuàng)建的對(duì)象??椚?Weaving) “織入”是把切面應(yīng)用到目標(biāo)對(duì)象來(lái)創(chuàng)建新的代理對(duì)象的過(guò)程。切面在指定連接點(diǎn)織入到目標(biāo)對(duì)象。SUNWAH
織入的時(shí)機(jī):? 編譯時(shí):切面在目標(biāo)類編譯時(shí)被織入。? 類加載時(shí):切面在目標(biāo)類加載到JVM時(shí)被織入。? 運(yùn)行時(shí):切面在程序運(yùn)行時(shí)的某個(gè)時(shí)刻被織入。
SUNWAH3.1.2Spring對(duì)AOP的支持創(chuàng)建切點(diǎn)來(lái)定義切面織入的連接點(diǎn)是AOP框架的基本功能。Spring對(duì)AOP的支持具有以下4種情況: ?經(jīng)典的基于代理的AOP?@AspectJ注解驅(qū)動(dòng)的切面?純POJO切面?注入式AspectJ切面 前三種都是基于代理的AOP的變體,因此,Spring對(duì)于AOP的支持局限于方法注入。SUNWAH
Spring的AOP框架的幾個(gè)關(guān)鍵點(diǎn):Spring通知是用JAVA編寫(xiě)的。 Spring創(chuàng)建的全部通知都是用標(biāo)準(zhǔn)JAVA類編寫(xiě)的。定義通知所應(yīng)用的切點(diǎn)通常是以XML方式寫(xiě)在Spring配置文件里。Spring在運(yùn)行時(shí)通知對(duì)象。 Spring利用代理類包裹切面,從而把它們織入到Spring管理的Bean里。代理類裝作目標(biāo)Bean,截取被通知的方法調(diào)用,再把這些調(diào)用轉(zhuǎn)發(fā)到真正的目標(biāo)Bean。在代理截取方法調(diào)用之后,實(shí)際調(diào)用目標(biāo)Bean的方法之前,代理會(huì)執(zhí)行切面邏輯。Spring只支持方法連接點(diǎn)。由于Spring是基于動(dòng)態(tài)代理的,它只支持方法連接點(diǎn)。SUNWAH3.2創(chuàng)建經(jīng)典的Spring切面定義一個(gè)觀眾類: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.");}//關(guān)閉自己的手機(jī)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種類型的通知,分別由一個(gè)接口進(jìn)行定義:通知類型接口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;/**
*
*
定義觀眾功能如何被使用的通知(實(shí)現(xiàn)了三種類型的通知)
*
*/public
classAudienceAdviceimplementsMethodBeforeAdvice,AfterReturningAdvice,ThrowsAdvice{publicAudienceAdvice(){}SUNWAH
//在方法之前調(diào)用public
voidbefore(Methodmethod,Object[]args,Objecttarget)throwsThrowable{audience.takeSeats();audience.turnOffCellPhones();}//在成功返回之后調(diào)用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周圍通知周圍通知相當(dāng)于前通知、返回后通知、拋出后通知的結(jié)合。在Spring里,周圍通知是由AOPAlliance的MethodInterceptor接口定義的。編寫(xiě)周圍通知的好處:
?能以簡(jiǎn)潔的方式在一個(gè)方法里定義前通知和后通知。
?可以檢查和修改被通知方法的返回值。
SUNWAH
以周圍通知方式定義觀眾通知:packagecom.sunwah.training.spring.aop;importercept.MethodInterceptor;importercept.MethodInvocation;importcom.sunwah.training.spring.di.PerformanceException;/**
*
*
以周圍通知方式定義觀眾通知
*
*/public
classAudienceAroundAdviceimplementsMethodInterceptor{SUNWAH
publicObjectinvoke(MethodInvocationinvocation)throwsThrowable{try{//在方法調(diào)用前執(zhí)行audience.takeSeats();audience.turnOffCellPhones();//調(diào)用目標(biāo)方法ObjectreturnValue=ceed();//在成功返回之后執(zhí)行audience.applaud();returnreturnValue;}catch(PerformanceExceptionthrowable){//出現(xiàn)異常之后執(zhí)行audience.demandRefund();throwthrowable;}}SUNWAH
//injectedprivateAudienceaudience;public
voidsetAudience(Audienceaudience){this.audience=audience;}}SUNWAH3.2.2定義切點(diǎn)和通知者連接點(diǎn)就是程序代碼里切面通知可以被織入的地點(diǎn)。切點(diǎn)是以某種方式選擇全部連接點(diǎn)的一個(gè)子集來(lái)定義通知應(yīng)該被織入的地點(diǎn)。
SUNWAH聲明正則表達(dá)式切點(diǎn)定義切點(diǎn):<bean
id="performancePointcut"
class="org.springframework.aop.support.JdkRegexpMethodPointcut"><property
name="pattern"
value=".*perform"
/></bean>類JdkRegexpMethodPointcut實(shí)現(xiàn)正則表達(dá)式切點(diǎn)。pattern屬性用于指定方法匹配所使用的切點(diǎn)模板。
SUNWAH
將切點(diǎn)與通知相關(guān)聯(lián):<bean
id="audienceAdvisor"
class="org.springframework.aop.support.DefaultPointcutAdvisor"><property
name="advice"
ref="audienceAdvice"
/><property
name="pointcut"
ref="performancePointcut"
/></bean>DefaultPointcutAdvisor類是個(gè)通知者類,它只是把通知關(guān)聯(lián)到一個(gè)切點(diǎn)。
SUNWAH
聯(lián)合切點(diǎn)與通知者:<bean
id="audienceAdvisor"class="org.springframework.aop.support.RegexpMethodPointcutAdvisor"><property
name="advice"
ref="audienceAdvice"
/><property
name="pattern"
value=".*perform"
/></bean>RegexpMethodPointcutAdvisor是個(gè)特殊的通知者類,可以在一個(gè)Bean里定義切點(diǎn)和通知者。
SUNWAH聲明AspectJ切點(diǎn)定義切點(diǎn):<bean
id="performancePointcut"class="org.springframework.aop.aspectj.AspectJExpressionPointcut"><property
name="expression"
value="execution(**.perform(..))"
/></bean>這里使用AspectJExpressionPointcut類而不是JdkRegexpMethodPointcut類。切點(diǎn)表達(dá)是被定義為expression屬性的值。
SUNWAH
將切點(diǎn)與通知相關(guān)聯(lián):<bean
id="audienceAdvisor"
class="org.springframework.aop.support.DefaultPointcutAdvisor"><property
name="advice"
ref="audienceAdvice"
/><property
name="pointcut"
ref="performancePointcut"
/></bean>DefaultPointcutAdvisor類是個(gè)通知者類,它只是把通知關(guān)聯(lián)到一個(gè)切點(diǎn)。
SUNWAH
聯(lián)合切點(diǎn)與通知者:<bean
id="audienceAdvisor"class="org.springframework.aop.aspectj.AspectJExpressionPointcutAdvisor"><property
name="advice"
ref="audienceAdvice"
/><property
name="expression"
value="execution(**.perform(..))"
/></bean>AspectJExpressionPointcutAdvisor是個(gè)通知者類,用來(lái)同時(shí)定義切點(diǎn)和通知者。
SUNWAH3.2.3使用ProxyFactoryBean作為被通知者通知的Bean,它必須是被代理的。Spring的ProxyFactoryBean是個(gè)工廠Bean,用于生成一個(gè)代理,把一個(gè)或多個(gè)(通知)應(yīng)用到Bean。target屬性指明哪個(gè)Bean被代理;interceptorNames屬性指明哪些通知者要應(yīng)用于被代理的Bean;proxyInterfaces屬性指明代理應(yīng)該實(shí)現(xiàn)哪些接口。
SUNWAH
定義演出者Duke的目標(biāo)Bean:<!--定義演出者Duke目標(biāo)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目標(biāo)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. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝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ù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
- 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ì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 圖書(shū)館志愿服務(wù)活動(dòng)實(shí)施方案
- 小學(xué)語(yǔ)言文字游戲化學(xué)習(xí)方案
- 智能制造企業(yè)信息技術(shù)方案
- 老舊公路改建路基施工方案
- 新能源項(xiàng)目監(jiān)理實(shí)施方案
- 2024年大數(shù)據(jù)分析與咨詢服務(wù)技術(shù)轉(zhuǎn)讓合同
- 2(2024版)網(wǎng)絡(luò)游戲虛擬物品交易合同
- 2024年農(nóng)產(chǎn)品批銷代理合同
- 2(2024版)大數(shù)據(jù)分析服務(wù)合同數(shù)據(jù)管理與應(yīng)用
- 2024年大數(shù)據(jù)科技有限公司數(shù)據(jù)處理合同
- 中國(guó)各區(qū)域矢量地圖素材(詳細(xì)到省市、能編輯)
- 蘇教版四年級(jí)下冊(cè)數(shù)學(xué)《解決問(wèn)題的策略-畫(huà)示意圖》課件(區(qū)級(jí)公開(kāi)課)
- 《新員工培訓(xùn)課件:企業(yè)文化及價(jià)值觀》
- 商務(wù)談判與推銷技巧課件
- 波峰焊治具設(shè)計(jì)規(guī)范
- 鈦白硫酸衡算
- 《先輩們唱過(guò)的歌》 單元作業(yè)設(shè)計(jì)
- 滿族介紹(課堂PPT)
- 小學(xué)生主題班會(huì)教學(xué)設(shè)計(jì) 隊(duì)會(huì)《男女平等》 通用版
- 工貿(mào)企業(yè)重大事故隱患判定標(biāo)準(zhǔn)培訓(xùn)PPT
- 實(shí)驗(yàn)室安全準(zhǔn)入教育(通識(shí)A課程)學(xué)習(xí)通超星課后章節(jié)答案期末考試題庫(kù)2023年
評(píng)論
0/150
提交評(píng)論