一. 捕获方法调用
        使用call(Signature)切入点。其语法:
         pointcut <pointcut name>(
<any values to be picked up>) : 
            call (
<optional modifier> <return type> <class>.<method>(<paramater type>));
         1. 在方法调用上触发通知,其环境是调用类。
         2. Signature可以包含通配符,用于选择不同类和方法上的一系列连接点。
    
        
            | 具有通配符的签名 | 描述 | 
        
            | * void MyClass.foo(int , float) | 无论修饰符是什么,都会捕获方法上的连接点。也可以忽略修饰符的可见性来做到这一点。 | 
        
            | void MyClass.foo(int , float) | 
        
            | * * MyClass.foo(int , float) | 无论修饰符或返回类型是什么,都会捕获方法上的连接点。 | 
        
            | * MyClass.foo(int , float) | 
        
            | * * *.foo(int , float) | 无论修饰符,返回类型或类是什么,都会捕获方法上的连接点。 | 
        
            | * *.foo(int , float) | 
        
            | * * *.*(int , float) | 无论修饰符,返回类型,类或者方法是什么,都会捕获方法上的连接点。 | 
        
            | * * *.*(* , float) | 无论修饰符,返回类型,类,或者其中的参数包含任何内容并且后接一个浮点数的方法是什么,都会捕获方法上的连接点。 | 
        
            | * * *.*(* , ..) | 无论修饰符,返回类型,类,或者其中的参数包含至少一个单值并且后接任意数量的方法是什么,都会捕获方法上的连接点。 | 
        
            | * * *.*(..) | 无论修饰符,返回类型,类,或者其中有任意数量参数的方法是什么,都会捕获方法上的连接点。 | 
        
            | * *(..) | 
        
            | * mypackage..*.*(..) | 捕获mypackage包和子包内的任何方法上的连接点。 | 
        
            | * MyClass+.*(..) | 捕获MyClass和任何子类中任何方法上的连接点。 | 
    
    
        我们来看一个最简单的例子:
 package com.aspectj;
package com.aspectj;


 public aspect CallRecipe
public aspect CallRecipe  {
{

 /**//*
    /**//*
 * Specifies calling advice whenever a mehtod
     * Specifies calling advice whenever a mehtod
 * matching the following rules gets called:
     * matching the following rules gets called:
 *
     * 
 * Class Name: MyClass
     * Class Name: MyClass
 * Method Name: foo
     * Method Name: foo
 * Method Return Type: void
     * Method Return Type: void
 * Method Parameters: an int followed by a String
     * Method Parameters: an int followed by a String
 */
     */
 pointcut callPointCut() : call(void MyClass.foo(int , String));
    pointcut callPointCut() : call(void MyClass.foo(int , String));
 
    
 //Advice declaration
    //Advice declaration

 before() : callPointCut()
    before() : callPointCut()  {
{
 System.out.println("------------------- Aspect Advice Logic -------------------");
        System.out.println("------------------- Aspect Advice Logic -------------------");
 System.out.println("In the advice attached to the call point cut");
        System.out.println("In the advice attached to the call point cut");
 System.out.println("Actually executing before the point cut call");
        System.out.println("Actually executing before the point cut call");
 System.out.println("But that's a recipe for Chapter 6!");
        System.out.println("But that's a recipe for Chapter 6!");
 System.out.println("signature: " + thisJoinPoint.getStaticPart().getSignature());
        System.out.println("signature: " + thisJoinPoint.getStaticPart().getSignature());
 System.out.println("Source Line: " + thisJoinPoint.getStaticPart().getSourceLocation());
        System.out.println("Source Line: " + thisJoinPoint.getStaticPart().getSourceLocation());
 System.out.println("------------------------------------------");
        System.out.println("------------------------------------------");
 }
    }

 }
}

    这样的一个方面可能执行下来的结果是这样的:
 ------------------- Aspect Advice Logic -------------------
------------------- Aspect Advice Logic -------------------
 In the advice attached to the call point cut
In the advice attached to the call point cut
 Actually executing before the point cut call
Actually executing before the point cut call
 But that's a recipe for Chapter 6!
But that's a recipe for Chapter 6!
 signature: void com.aspectj.MyClass.foo(int, String)
signature: void com.aspectj.MyClass.foo(int, String)
 Source Line: MyClass.java:10
Source Line: MyClass.java:10
 -----------------------------------------------------------
-----------------------------------------------------------

 foo(int , String)
foo(int , String) 
        这里有一个报告需要提醒一下。我们先运行如下代码:
 package com.aspectj;
package com.aspectj;


 public class Test extends MyClass
public class Test extends MyClass {
{

 public void foo(int age , String name)
    public void foo(int age , String name)  {
{
 System.out.println("foo(int , String)");
        System.out.println("foo(int , String)");
 }
    }
 
    

 public static void main(String[] args)
    public static void main(String[] args)  {
{
 Test c = new Test();
        Test c = new Test();
 c.foo(3 , "name");
        c.foo(3 , "name");
 }
    }

 }
}        Test.java是MyClass.java的子类,并重写了foo(int , String)方法。按照Java正常的执行方法,运行Test.java是不会牵涉到任何方面的,但事实相反,callPointCut()通知还是会被执行。这就是AspectJ设计的比较妖怪的地方。对此,http://www.eecs.ucf.edu/~leavens/FOAL/papers-2004/barzilay-etal.pdf 有详细的描述。有兴趣的朋友可以研究一把。
/Files/zhengzhili/Call_and_Execution_Semantics_in_AspectJ.pdf
二. 捕获方法调用上传递的参数值
    可以使用call(Signature)和args([TypePatterns | Identifiers])切入点来捕获对方法的调用,然后把需要的标识符绑定到方法的参数值上。
 package com.aspectj;
package com.aspectj;


 public aspect CaptureCallPamaterRrecipe
public aspect CaptureCallPamaterRrecipe  {
{

 /**//*
    /**//*
 * Specifies calling advice whenever a mehtod
     * Specifies calling advice whenever a mehtod
 * matching the following rules gets called:
     * matching the following rules gets called:
 *
     * 
 * Class Name: MyClass
     * Class Name: MyClass
 * Method Name: foo
     * Method Name: foo
 * Method Return Type: void
     * Method Return Type: void
 * Method Parameters: an int followed by a String
     * Method Parameters: an int followed by a String
 */
     */
 pointcut captureCallPamaters(int value , String name) : call(void MyClass.foo(int , String)) && args(value , name);
    pointcut captureCallPamaters(int value , String name) : call(void MyClass.foo(int , String)) && args(value , name);
 
    
 
    
 //Advice declaration
    //Advice declaration

 before(int value , String name) : captureCallPamaters(value , name)
    before(int value , String name) : captureCallPamaters(value , name)  {
{
 System.out.println("------------------- Aspect Advice Logic -------------------");
        System.out.println("------------------- Aspect Advice Logic -------------------");
 System.out.println("In the advice attached to the call point cut");
        System.out.println("In the advice attached to the call point cut");
 System.out.println("Captured int parameter on method: " + value);
        System.out.println("Captured int parameter on method: " + value);
 System.out.println("Captured String parameter on method: " + name);
        System.out.println("Captured String parameter on method: " + name);
 System.out.println("------------------------------------------");
        System.out.println("------------------------------------------");
 }
    }    
 }
}

        上例中个人理解为两次绑定过程。第一次captureCallPamaters通过args([Types | Identifiers])将foo方法的参数绑定到自己的参数上;第二次再把自己的参数绑定到before()上。也因此,1. pointcut captureCallPamaters(int value , String name) : call(void MyClass.foo(int , String)) && args(value , name); 中参数名必须一一对应;2.before(int value , String name) : captureCallPamaters(value , name) 中参数名也必须一一对应。而1和2之间的参数名则不需要一一对应。
三. 捕获方法调用的目标
        使用call(Signature)和targer([Type | Identifier])切入点来捕获方法的调用,然后把单一标识符绑定到正在调用方法的对象上。
 package com.aspectj;
package com.aspectj;



 public aspect CaptureCallTargetRecipe
public aspect CaptureCallTargetRecipe  {
{

 /**//*
    /**//*
 * Specifies calling advice whenever a method
     * Specifies calling advice whenever a method
 * matching the following rules gets called:
     * matching the following rules gets called:
 *
     * 
 * Class Name: MyClass
     * Class Name: MyClass
 * Method Name: foo
     * Method Name: foo
 * Method Return Type: void
     * Method Return Type: void
 * Method Parameters: an int followed by a String
     * Method Parameters: an int followed by a String
 */
     */
 pointcut captureCallTarget(MyClass myObject) : call(void MyClass.foo(int , String)) && target(myObject);
    pointcut captureCallTarget(MyClass myObject) : call(void MyClass.foo(int , String)) && target(myObject);
 
    
 
    
 //Advice declaration
    //Advice declaration

 before(MyClass myObject) : captureCallTarget(myObject)
    before(MyClass myObject) : captureCallTarget(myObject)  {
{
 System.out.println("------------------- Aspect Advice Logic -------------------");
        System.out.println("------------------- Aspect Advice Logic -------------------");
 System.out.println("In the advice attached to the call point cut");
        System.out.println("In the advice attached to the call point cut");
 System.out.println("Captured target object for the method call: " + myObject);
        System.out.println("Captured target object for the method call: " + myObject);
 System.out.println("------------------------------------------");
        System.out.println("------------------------------------------");
 }
    }    
 }
}
四. 当执行一个方法时捕获它
        使用execution(Signature)切入点。其语法如下:
        pointcut <pointcut name>(<any values to be picked up>) :
            execution(<optional modifier> <return type> <class>.<method>(<paramater types>));
        execution(Signature)切入点具有两个关键特征:
        1。触发连接点的环境在目标类方法中。
        2。Signature可以包含通配符,以选择不同类和方法上的一系列连接点。
 package com.aspectj;
package com.aspectj;


 public aspect ExecutionRecipe
public aspect ExecutionRecipe  {
{

 /**//*
    /**//*
 * Specifies calling advice whenever a method
     * Specifies calling advice whenever a method
 * matching the following rules gets called:
     * matching the following rules gets called:
 *
     * 
 * Class Name: MyClass
     * Class Name: MyClass
 * Method Name: foo
     * Method Name: foo
 * Method Return Type: void
     * Method Return Type: void
 * Method Parameters: an int followed by a String
     * Method Parameters: an int followed by a String
 */
     */
 pointcut executionPointcut() : execution(void MyClass.foo(int , String));
    pointcut executionPointcut() : execution(void MyClass.foo(int , String));
 
    
 
    
 //Advice declaration
    //Advice declaration

 before() : executionPointcut() && !within(ExecutionRecipe +)
    before() : executionPointcut() && !within(ExecutionRecipe +)  {
{
 System.out.println("------------------- Aspect Advice Logic -------------------");
        System.out.println("------------------- Aspect Advice Logic -------------------");
 System.out.println("In the advice picked by ExecutionRecipe");
        System.out.println("In the advice picked by ExecutionRecipe");
 System.out.println("signature: " + thisJoinPoint.getStaticPart().getSignature());
        System.out.println("signature: " + thisJoinPoint.getStaticPart().getSignature());
 System.out.println("Source Line: " + thisJoinPoint.getStaticPart().getSourceLocation());
        System.out.println("Source Line: " + thisJoinPoint.getStaticPart().getSourceLocation());
 System.out.println("------------------------------------------");
        System.out.println("------------------------------------------");
 }
    }    
 }
}

        上述代码和第一部分所使用的call(Signature)切入点相比,没什么新的内容。但请注意是什么地方调用通知,以及它的环境是什么。即请特别关注thisJoinPoint.getStaticPart().getSourceLocation()的返回值。
        
五. 在执行方法时捕获this引用的值 
       在执行期间捕获方法时,想通过显示Java的this引用所指向的对象,使之可以被通知使用,可以使用execute(Signature)和this(Type | Identifier)切入点来捕获方法的执行,并把单一标识符绑定到方式执行期间this引用所指向的对象。
 package com.aspectj;
package com.aspectj;


 public aspect CaptureThisReferenceRecipe
public aspect CaptureThisReferenceRecipe  {
{

 /**//*
    /**//*
 * Specifies calling advice whenever a mehtod
     * Specifies calling advice whenever a mehtod
 * matching the following rules gets called:
     * matching the following rules gets called:
 *
     * 
 * Class Name: MyClass
     * Class Name: MyClass
 * Method Name: foo
     * Method Name: foo
 * Method Return Type: void
     * Method Return Type: void
 * Method Parameters: an int followed by a String
     * Method Parameters: an int followed by a String
 */
     */
 pointcut captureThisDuringExecution(MyClass myObject) :
    pointcut captureThisDuringExecution(MyClass myObject) :
 execution(void MyClass.foo(int , String)) && this (myObject);
        execution(void MyClass.foo(int , String)) && this (myObject);
 
    
 //Advice declaration
    //Advice declaration

 before(MyClass myObject) : captureThisDuringExecution(myObject)
    before(MyClass myObject) : captureThisDuringExecution(myObject)  {
{
 System.out.println("------------------- Aspect Advice Logic -------------------");
        System.out.println("------------------- Aspect Advice Logic -------------------");
 System.out.println("In the advice attached to the execute point cut");
        System.out.println("In the advice attached to the execute point cut");
 System.out.println("Captured this reference: " + myObject);
        System.out.println("Captured this reference: " + myObject);
 System.out.println("------------------------------------------");
        System.out.println("------------------------------------------");        
 }
    }
 }
}
