??? ??? call
和
execution
的指示符分別為
call
(
Method-Signature
)、
execution
(
Method-Signature
),匹配方法簽名的方法或構造函數的執行。
對于
call
來說,調用的連接點位于方法調用點的調用代碼處;對于
execution
來說,執行的連接點位于方法執行的位置。也就是說,
call
和
execution
的重要區別在于它們傳遞了哪些類型給
AspectJ
編譯器以用來與
aspect
進行鏈接。
??? ??? 通常,我們在使用
call
和
execution
時,從效果上來看并不會覺察出二者的區別。下面給出一個例子說明
call
和
execution
的運行時機及區別。
??? ? public?class?A??{
????public?void?foo(){
????????System.out.println("A.foo()");
????}
}
public?class?Main?{
????public?void?callFoo(A?a){
????????a.foo();
????}
????public?static?void?main(String[]?args)?{????
????????Main?m?=?new?Main();
????????m.callFoo(new?A());
????}
}
??? ??? 1
)現在我看一下下面使用
call
的切面:
?
?????????????????????
???
??? ??? ?? 該切面定義了一個切入點callA(Object
o,Object
t),其中this(o)表示將匹配的連接點的對象賦給o,target(t)表示將匹配的連接點的目標對象賦給t。輸出結果為:
??? ??? ?? 
??? ?? ?
??? ??? 輸出表明,this的類(調用類)為Main,target的類(目標類)為A。我們再看一下Main類:
??? ?? 
??? ??? 在AJDT下,可以看到,call切入點匹配的位置在調用類(Main)的方法void
callFoo(A a)中,而不是在目標類A中。
??? ??? 2)再來看一下execution的例子:
??? ?? 
?? ?? 
??? ??? 在這個方面中,切入點沒有使用this和target,而是在before通知中使用了AspectJ的API達到同樣的效果。可以看到,切入點executionA()匹配的連接點的位置在A的foo()方法,這和上面的call匹配的連接點的位置是不同的。
??? ?? 
?? ?
??? ??
??? ??? 從輸出可以看到,在execution中,this和target指向同一個類。在call中,this和target不是指向同一個類。
??? ??? execution與call還有一點很重要的區別。對于繼承類來說,如果它沒有覆蓋父類的方法,那么execution不會匹配子類中沒有覆蓋父類的方法。比如說我們有一個類B繼承于A,但沒有覆蓋A類的foo(),那么對于B的實例的foo()方法,execution(*
B.foo())將不會被匹配。
??? ??? 做個總結,如果想跟蹤連接點的內部代碼運行情況可以考慮使用execution,但如果你只關心連接點的簽名(比如你使用第三方庫或是標準API),則使用call。
??? ??? 注:該文參考了《Eclipse
AspectJ》和《AspectJ
cookbook》。