接上一篇文章,在上午中使用了切面作防重複控制,本文着重介紹切面AOP。spring
在開發中,有一些功能行爲是通用的,好比、日誌管理、安全和事務,它們有一個共同點就是分佈於應用中的多處,這種功能被稱爲橫切關注點(cross-cutting concerns)。編程
DI(依賴注入)有助於應用對象之間的解耦,而AOP能夠實現橫切關注點與他們所影響的對象之間的解耦。安全
面向切面編程在Spring AOP中有4種類型的調用,方法調用的以前、後、異常增長其餘方法,方法調用的前和後調用其餘方法,將方法中的參數傳遞給其餘方法,講一個嶄新額的接口實現做爲父類接口給其餘方法所屬的方法。咱們在調用某個方法的時候,Spring AOP在其餘勒種就爲這個方法額外作了其餘事情。ide
繼承和委託是最多見的實現通用功能的面向對象技術,切面提供了取代繼承和委託的另外一種選擇,並且在不少場景下更清晰簡潔。模塊化
在使用面向切面編程時,咱們仍然在一個地方定義通用功能,可是咱們能夠提供聲明的方式定義這個功能以何種方式在何處應用,而無需修改受影響的類,this
橫切關注點能夠被模塊化爲特殊的類,這些類被稱爲切面。spa
切面是一個類,這個可的做用是完成對指定位置的指定動做的附屬動做,指定位置首先有一個選擇範圍,能夠是建立對象、方法調用、變量改變等等,這些選擇範圍就是鏈接點,你能夠決定選取其中的一部分,這些被選中的部分就是切點,固然選擇的過程在代碼中實現,選好點後,一旦這些點被運行了,好比調用了一個類,切面裏的類中的某個方法就會被調用,以完成別的功能,這個被調用的方法就是通知。代理
即:日誌
一、通知(Advice) 5種類型xml
切面的工做被稱爲通知
通知定義了切面的什麼以及什麼時候使用,除了描述切面要完成的工做,通知還解決了什麼時候執行這個工做的問題。
根據應用於方法以前、後、先後、異常等能夠分爲
二、鏈接點(Joinpoint)
鏈接點是在應用執行過程當中可以插入切面的一個點,準確的說是程序運行中的某種時機,好比調用方法時,拋出異常時、甚至是修改一個字段時。切面代碼能夠利用這些點(時機)插入到應用的正常流程之中,並添加新的行爲。
三、切點(Pointcut)
一個切面僅僅須要通知有限的鏈接點而不是所有的鏈接點,切點定義了鏈接點中的哪些是通知須要產生做用的,
切點會匹配通知所要織入的一個或者多個鏈接點
咱們一般使用明確的類和方法名稱來指定這些切點
簡單的說,切點是相對於不一樣通知而言的有效鏈接點的集合
四、切面(Aspect)
切面是通知和切點的集合,通知決定作什麼?什麼時候?切點決定在那些地方進行通知。
五、引入(Introduction)
引入是一個過程的描述,指咱們向現有的類添加新方法或屬性。咱們能夠把一個類做爲通知,引入到被通知的類中,從而在不改變被通知的類的狀況下改變這個類。
六、織入(Weaving)
切面在指定的鏈接點(即通知在切點通知被通知的方法,通知被引入了被通知的類)被織入到目標對象中,括號中一直說被通知類增長了方法,這種增長的方法就是織入,說到底,織入是爲被通知類建立了代理類,在代理類中增長了方法。從表面看來,被代理類增長了方法,即織入。
織入是將切面應用到目標對象來建立新的代理對象的過程。切面在指定的鏈接點被織入到目標對象中。
在目標對象的多個點能夠進行織入。
經過在代理類中包裹切面,Spring在運行期將切面織入到Spring管理的Bean中。
編譯期——切面在目標類編譯時被織入。
·這種方式須要特殊的編譯器。
·AspectJ的織入編譯器就是以這種方式織入切面的。
類加載期——切面在目標類加載到JVM時被織入。
·這種方式須要特殊的類加載器(ClassLoader),它能夠在目標類被引入應用以前加強該目標類的字節碼。
·AspectJ 5的LTW(load-time weaving)就支持以這種方式織入切面。
運行期——切面在應用運行期間的某個時段被織入。
·通常狀況下,在織入切面時,AOP容器會爲目標對象動態地建立一個代理對象。
·Spring AOP 就是在運行期,爲目標對象動態建立一個代理對象來實現織入的。當攔截到方法調用時。在調用目標Bean以前,代理會執行切面邏輯。直到應用須要被代理的Bean時,Spring才建立代理對象。
一、Spring提供了4種各具特點的AOP支持
前3種都是Spring基於代理的AOP變體,所以,Spring對AOP的支持侷限於方法攔截。若是AOP需求超過了簡單方法攔截的範疇(如構造器或屬性攔截),那麼應該考慮在AspectJ裏實現切面,利用Spring的DI(依賴注入)把Spring Bean注入到AspectJ切面中:
二、Spring只支持方法鏈接點
AspectJ和Jboss除了方法切點,還提供了字段和構造器接入點。因此,單單使用Spring咱們沒法構建細粒度的通知,也沒法使用構造器鏈接點。對於這種狀況,咱們能夠利用Aspect來協助Spring AOP。
三、切點規定了那些鏈接點
咱們使用切點來選擇鏈接點,而後是不一樣的通知匹配不一樣的切點。在Spring AOP中,須要使用AspectJ的切點表達式來定義切點。
四、Spring AOP所支持的AspectJ切點指示器
arg() 限制鏈接點匹配參數爲指定類型的執行方法
@args() 限制鏈接點匹配參數由指定註解標註的執行方法
execution() 用於匹配是鏈接點的執行方法
this() 限制鏈接點匹配AOP代理的Bean引用爲指定類型的類
target() 限制鏈接點匹配目標對象爲指定類型的類
@target() 限制鏈接點匹配特定的執行對象,這些對象對應的類要具有指定類型的註解
within() 限制鏈接點匹配指定的類型
@within() 限制鏈接點匹配指定註解所標註的類型(當使用Spring AOP時,方法定義在由指定的註解所標註的類裏)
@annotation 限制匹配帶有指定註解鏈接點
只有execution切點指示器是惟一的執行匹配,而其餘的切點指示器都是用於限制匹配的。
五、編寫切點,這些最後被添加到xml配置文件中
注意:所寫的路徑都是接口類的路徑,切點是在接口類中而不是具體的實現類中的。
不關注返回類型,不關注入參類型,在方法執行的時候引入切點
execution(* com.springination.springidol.Instrument.play(..))
增長限制-而且限定了切點的包路徑(後者是多餘的嗎?)
execution(* com.springination.springidol.Instrument.play(..))
and within(com.springinaction.springidol.*)
在spring2.5以後,能夠經過id來限定bean
execution(* com.springination.springidol.Instrument.play(..))
and within(com.springinaction.springidol.*)
and bean(eddie)
固然也可使用反向操做
execution(* com.springination.springidol.Instrument.play(..))
and within(com.springinaction.springidol.*)
and bean(eddie)
and !bean(eddie2)
六、在XML中聲明切面
AOP配置元素 描述
<aop:advisor> 定義AOP通知器
<aop:after> 定義AOP後置通知(無論被通知的方法是否執行成功)
<aop:after-returning> 定義AOP after-returning通知
<aop:after-throwing> 定義after-throwing通知
<aop:around> 定義AOP環繞通知
<aop:aspect> 定義切面
<aop:aspect-autoproxy> 啓用@AspectJ註解驅動的切面
<aop:before> 定義AOP前置通知
<aop:config> 頂層的AOP配置元素。大多數的<AOP:*>元素,必須包含在 <aop:config>元素內
<aop:declare-parents> 爲被通知的對象引入額外的接口,並透明地實現
<aop:pointcut> 定義切點