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 開頭而且有兩個參數的方法,第二個參數必須是
String
execution(* 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,..)
表示至少有一個參數。