Spring-AOP 切點/切面型別和建立切面
概述
前面的博文介紹增強的時候,我們發現一個問題:增強被織入到了目標類的所有方法中.
如果我們希望有選擇的織入目標類的某些特定方法中呢? ——–這個時候就需要使用切點進行目標連線點的定位。
描述連線點是進行AOP程式設計最主要的工作,我們來說下Spring AOP如何定位連線點。
增強提供了連線點方位資訊,如織入到方法前面、後面等,而切點進一步描述了織入哪些類的哪些方法上
Spring通過org.springframework.aop.Pointcut介面描述切點,Pointcut由ClassFilter和MethodMatcher構成,它
- 通過ClassFilter定位到某個特定的類上,
- 通過MethodMatcher定位到某些特定方法上。
這樣Pointcut就擁有了某些類的某些特定方法的能力。
ClassFilter中定義了唯一的方法
boolean matches(Class<?> clazz);
入參為一個被檢測的類,該方法判斷被檢測的類是否匹配過濾條件。
Spring支援兩種方法匹配器
靜態方法匹配器
所謂靜態方法匹配器,僅對方法名簽名(包括方法名和入參型別及順序)進行匹配。
動態方法匹配器
動態方法匹配器會在執行期方法檢查入參的值。 靜態匹配僅會判斷一次,而動態匹配因為每次呼叫方法的入參可能不一樣,所以每次呼叫方法都必須判斷。
因此,動態匹配對效能的影響很大,一般情況下,動態匹配器不常用。 方法匹配器的型別由MethodMatcher介面的isRuntime方法的返回值決定, 返回false標識靜態方法匹配器,true標識位動態方法匹配器。
六種切點型別
靜態方法切點StaticMethodMatcherPointcut
org.springframework.aop.support.StaticMethodMatcherPointcut是靜態方法切點的抽象基類,預設情況下匹配所有的類。
最常用的兩個子類如上所示,分別是 NameMatchMethodPointcut 和 AbstractRegexpMethodPointcut , 前者提供簡單字串匹配方法簽名,後者使用正則表示式匹配方法簽名。
動態方法切點DynamicMethodMatcher
org.springframework.aop.support.DynamicMethodMatcher是動態方法切點的抽象基類,預設情況下匹配所有的類
註解切點AnnotationMatchingPointcut
org.springframework.aop.support.annotation.AnnotationMatchingPointcut實現類標識註解切點。 使用AnnotationMatchingPointcut支援在Bean中直接通過Java5.0註解標籤定義切點
表示式切點ExpressionPointcut
org.springframework.aop.support.ExpressionPointcut介面主要是為了支援AspectJ切點表示式語法而定義的介面
流程切點ControlFlowPointcut
org.springframework.aop.support.ControlFlowPointcut實現類標識控制流程切點。 ControlFlowPointcut是一種特殊的切點,它根據程式執行堆疊的資訊檢視目標方法是否由某一個方法直接或間接發起呼叫,以此判斷是否為匹配的連線點。
複合切點ComposablePointcut
org.springframework.aop.support.ComposablePointcut實現類是為了建立多個切點而提供的方便操作類。 它所有的方法都返回ComposablePointcut類,這樣就可以使用連結表示式對切點進行操作,形如
Pointcut pc = new ComposalbePointcut().union(classFilter).intersection(methodMatcher).intersection(pointcut);
三種切面型別
由於增強包括橫切程式碼,又包含部分連線點資訊(方法前、方法後主方位資訊),所以可以僅通過增強類生成一個切面。 但切點僅僅代表目標類連線點的部分資訊(類和方法的定位),所以僅有切點無法制作出一個切面,必須結合增強才能製作出切面。
Spring使用org.springframework.aop.Advisor介面標識切面概念,一個切面同時包含橫切程式碼和連線點資訊。
切面可以分為3類:一般切面、切點切面、引介切面
我們來看下切面繼承關係
一般切面Advisor
org.springframework.aop.Advisor代表一般切面,僅包含一個Advice
因為Advice包含了橫切程式碼和連線點資訊,所以Advice本身一個簡單的切面,只不過它代表的橫切的連線點是所有目標類的所有方法,因為這個橫切面太寬泛,所以一般不會直接使用。
切點切面PointcutAdvisor
org.springframework.aop.PointcutAdvisor ,代表具有切點的切面,包括Advice和Pointcut兩個類,這樣就可以通過類、方法名以及方位等資訊靈活的定義切面的連線點,提供更具實用性的切面。
PointcutAdvisor介面實現類
PointcutAdvisor主要有6個具體的實現類:
DefaultPointcutAdvisor
最常用的切面型別,它可以通過任意Pointcut和Advice定義一個切面,唯一不支援的就是引介的切面型別,一般可以通過擴充套件該類實現自定義的切面
NameMatchMethodPointcutAdvisor
通過該類可以定義按方法名定義切點的切面
RegexpMethodPointcutAdvisor
對於按照正則表示式匹配的方法名進行切點定義的切面,可以擴充套件該實現類進行操作。
AspectJExpressionPointcutAdvisor
用於AspectJ切點表示式定義切點的切面
StaticMethodMatcherPointcutAdvisor
靜態方法匹配器切點定義的切面,預設情況下匹配所有的的目標類。
AspectJPointcutAdvisor
用於AspectJ語法定義切點的切面
這些Advisor的實現類都可以在Pointcut中找到對應物,實際上,他們都是通過擴充套件對應的Pintcut實現類並實現PointcutAdvisor介面進行定義的。
比如StaticMethodMatcherPointcutAdvisor
public abstract class StaticMethodMatcherPointcutAdvisor extends StaticMethodMatcherPointcut
implements PointcutAdvisor, Ordered, Serializable
擴充套件了StaticMethodMatcherPointcut類並實現了PointcutAdvisor介面。
此外Advisor都實現了org.springframework.core.Ordered介面,Spring將根據Advisor定義的順序決定織入切面的順序。
引介切面IntroductionAdvisor
org.springframework.aop.IntroductionAdvisor代表引介切面, 引介切面是對應引介增強的特殊的切面,它應用於類層上面,所以引介切點使用ClassFilter進行定義。