Pointcut 表示式用來定義斷言,用以匹配、判斷某些方法呼叫是否要織入 Advice,Spring AOP 的 Pointcut 表示式主要借鏡自 AspectJ,然而並未全部支援,可使用的代號(designator)有以下幾個:
execution:最主要的表示式,用來匹配方法執行的 Join Point。within:必須是指定的型態,可用來取代某些execution模式。this:代理物件必須是指定的型態,常用於 Advice 中要取得代理物件之時。target:目標物件必須是指定的型態,常用於 Advice 中要取得目標物件之時。args:引數必須是指定的型態,常用於 Advice 中要取得方法引數之時。。@target:目標物件必須擁有指定的標型,常用於 Advice 中要取得標註之時。@args:引數必須擁有指定的標註,常用於 Advice 中要取得標註之時。@within:必須擁有指定的標註,常用於 Advice 中要取得標註之時。@annotation:方法上必須擁有指定的標註,常用於 Advice 中要取得標註之時。
execution 是最常使用的表示式代號,可撰寫的模式為:
execution(modifiers-pattern? ret-type-pattern declaring-type-pattern? name-pattern(param-pattern)
throws-pattern?)
模式中的 ? 表示選擇性設置,也就是除了 ret-type-pattern、name-pattern 與 param-pattern 為必要之外,其他都可以選擇性地設置,沒有設置的話就是不限定;必要的設置可以使用 * 表示任意符號,.. 表示 0 或多個符號,+ 表示必須是指定型態的子型態。
以先前文件中經常看到的 execution(* cc.openhome.model.AccountDAO.*(..)) 為例,它表示沒有限定權限修飾,也就是 public、protected、private 或 default 方法都可以,第一個 * 設定傳回型態(ret-type-pattern)可以是任何型態,cc.openhome.model.AccountDAO.* 指定了名稱模式(name-pattern),其中的 * 表示任何方法,.. 表示任意數量引數。
來看看幾個設置的模式範例:
任何公開方法
execution(public * *(..))任何 accountBy 開頭的方法
execution(* accountBy*(..))accountBy 開頭而且有一個參數型態為
String的方法execution(* accountBy*(String))get 開頭而且無參數方法
execution(* get*())get 開頭而且有兩個參數的方法,第二個參數必須是
Stringexecution(* get*(*,String))get 開頭而且第一個參數必須是
String的方法execution(* get*(String,..))cc.openhome.model套件中任何型態的方法execution(* cc.openhome.model.*.*(..))cc.openhome.model套件或子套件中任何型態的方法execution(* cc.openhome.model.service..*.*(..))
within 限定必須是指定的型態,可以使用 * 或 ..,某些 execution 模式,可以使用 within 取代,例如:
within(cc.openhome.model.AccountDAO)相當於execution(* cc.openhome.model.AccountDAO.*(..))within(cc.openhome.model.*)相當於execution(* cc.openhome.model.*.*(..))within(cc.openhome.model..*)相當於execution(* cc.openhome.model.service..*.*(..))
Pointcut 表示式可以使用 &&、|| 與 ! 來作關係運算,例如在〈定義 Introduction〉中看過:
...略
@Around("execution(* cc.openhome.model.AccountDAO.*(..)) && this(nullable)")
public Object around(ProceedingJoinPoint proceedingJoinPoint, Nullable nullable) throws Throwable {
...略
這表示,必須是 cc.openhome.model.AccountDAO 型態上的方法,而且代理物件必須是 Nullable,因為使用了 &&,而且 this(nullable) 中的 nullable 表示,從 around 方法上與 nullable 同名的參數得知型態。
當然,如果只是想限定代理物件必須是 cc.openhome.aspect.Nullable,只要寫 this(cc.openhome.aspect.Nullable) 就可以了。
其他的代號與 this 類似,也都可以用來在 Advice 中取得對應的物件;args 若有多個引數要定義,可以使用 args(name, email) 這類的形式,或者也可以使用 args(name,..) 表示至少有一個參數。

