最爱Java

书山有路勤为径,学海无涯苦作舟

《AspectJ Cookbook》读书笔记十一: 捕获基于对象的连接点

         this([Type | Identifier])研究的是在捕捉的连接点处由this引用的对象的类型。连接点的目标(通过target([Type | Identifier])切入点指定)依赖于连接点类型而有所不同,但它常常是在其上调用方法的对象,或者是以某种方式访问的在其中遇到连接点的属性。连接点args(通过args([Types | identieters])切入点指定)就是在捕捉的连接点处可用的参数。
          可以用两种方式之一研究this,target和args引用的类型:使用静态Type指示,或者使用一个Identifier,它引用一个实际的运行时对象。
          Type指示对连接点处的对象类型提供了一个静态编译时评估,并且采用完全限定类名的形式(例如,com.oreilly.Foo是可接受的,但是Foo或Foo.class则不可接受)。
          Identifiers提供了一种方法,可以通过它来评估连接点处的运行时对象的实际类型,而不仅仅是静态类型。Identifier在运行时动态地赋予合适的对象。
 
一. 捕获何时this引用一个特定的类型问题
    使用this([Type | Identifier])切入点。this([Type | Identifier])切入点的语法如下:
    point <pointcut name>(<any values to be picked up>):this(<type> or <identifier> or *);

    this([Type | Identifier])切入点检查捕获的连接点处的this引用,以决定是否调用关联的通知,它具有5个关键特征:
    1. 当执行对象是指定的类型时,this([Type | Identifier])切入点会捕获所有连接点。
    2. Type定义参数必须解析成有效的类。它不同于TypePattern,TypePattern中可能使用通配符。
    3. Identifier用于检查this引用的运行时对象的类型,以及根据需要把那个对象展示给通知。
    4. 使用*通配符允许指定一个有效的对象,连接点处的this引用必须指向它,但是你对它是什么类型不感兴趣。
    5. 出现在异常处理上的连接点不具有使用handler(TypePattern)切入点的值,当他们使用任何静态代码块(包含使用staticinitialization(TypePattern)切入点指定的静态类初始化)内的handler(TypePattern),并且有趣地使用preinitializations(Signature)切入点预初始化对象时,它们将不具有使用this([Type|Identifier])切入点展示this引用的值。

    以下展示了this([Type | Identifier])切入点的两个示例:
        1.当this引用指向MyClass类型的对象时,使用Identifier捕获连接点
        2.当this引用的类型是AnotherClass时,使用Type指示捕获


 

package com.aspectj;

public aspect ThisRecipe {
    
/**
     * Specifies calling advice whenever the executing
     * object is of a type that matches the following rules:
     * 
     * Identifiers:MyClass object
     
*/

    pointcut thisIdentifierMyClassPointcut(MyClass object):
this(object);
    
/**
     * Specifies calling advice whenever the executing
     * object is of a type that matches the following rules:
     * 
     * Type Pattern:AnotherClass
     
*/
    
    pointcut thisTypePatternAnotherClassPointcut():
this(AnotherClass);
    
    
//Advice declaration
    before(MyClass object) : thisIdentifierMyClassPointcut(object) && !within(ThisRecipe+{
        System.out.println(
"---------- Aspect Advice Logic ----------");
        System.out.println(
"In the advice picked by thisIdentifierMyClassPointcut()");
        System.out.println(
"Join Point Kind" + thisJoinPoint.getKind());
        System.out.println(
"this reference as passed by identifier " + object);
        System.out.println(
"Object referenced by this: " + thisJoinPoint.getThis());
        System.out.println(
"Signature: " + thisJoinPoint.getStaticPart().getSignature());
        System.out.println(
"Source Line: " + thisJoinPoint.getStaticPart().getSourceLocation());
        System.out.println(
"-----------------------------------------");        
    }

    
    
//Advice declaration
    before() : thisTypePatternAnotherClassPointcut() && !within(ThisRecipe+{
        System.out.println(
"---------- Aspect Advice Logic ----------");
        System.out.println(
"In the advice picked by thisIdentifierMyClassPointcut()");
        System.out.println(
"Join Point Kind" + thisJoinPoint.getKind());
        System.out.println(
"Type of executing object: " + thisJoinPoint.getThis().getClass().getName());
        System.out.println(
"Object referenced by this: " + thisJoinPoint.getThis());
        System.out.println(
"Signature: " + thisJoinPoint.getStaticPart().getSignature());
        System.out.println(
"Source Line: " + thisJoinPoint.getStaticPart().getSourceLocation());
        System.out.println(
"-----------------------------------------");        
    }


}



二. 捕获何时连接点的目标对象是特定的类型
    使用target([Type|Identifier])切入点。target([Type|Identifier])切入点的语法如下:
    pointcut <pointcut name>(<any values to be picked up>) : target(<type> or <identifier> or *);
    target([Type|Identifier])切入点具有5个关键特征:
        1.当目标对象是特定的类型时,target([Type|Identifier])切入点将选择所有的连接点。
        2.Type定义参数必须解析成有效的类,以选择相关的连接点。它有别与TypePattern,TypePattern中可能使用通配符。
        3.Identifier用于检查在捕捉的连接点处被引用为目标的运行时对象的类型,并根据需要把那个对象展示给通知。
        4.使用*通配符允许指定连接点必须有一个目标,但是你对它类型是什么不感兴趣。
        5.在使用handler(TypePattern)切入点的异常处理上,使用staticinitialization(TypePattern)的静态类初始化,以及有趣地使用preinitialization(Signature)的对象初始化上,在这些地方出现的连接点不具有使用target([Type|Identifier])切入点进行展示的任何目标环境。

    以下显示了target([Type|Identifier])的两个示例:
    1.当目标是Identifier指定的MyClass对象时,捕获连接点
    2.当方法调用目标的类型是Type指定的AnotherClass时,捕获连接点


 

package com.aspectj;

public aspect TargetRecipe {
    
/**
     * Specifies calling advice whenever the executing
     * object is of a type that matches the following rules:
     * 
     * Identifiers:MyClass object
     
*/

    pointcut targetIdentifierMyClassPointcut(MyClass object):target(object);
    
/**
     * Specifies calling advice whenever the executing
     * object is of a type that matches the following rules:
     * 
     * Type Pattern:AnotherClass
     
*/
    
    pointcut targetTypePatternAnotherClassPointcut():target(AnotherClass);
    
    
//Advice declaration
    before(MyClass object) : targetIdentifierMyClassPointcut(object) && !within(TargetRecipe+{
        System.out.println(
"---------- Aspect Advice Logic ----------");
        System.out.println(
"In the advice picked by targetIdentifierMyClassPointcut()");
        System.out.println(
"Join Point Kind" + thisJoinPoint.getKind());
        System.out.println(
"this reference as passed by identifier " + object);
        System.out.println(
"Object referenced by this: " + thisJoinPoint.getThis());
        System.out.println(
"Signature: " + thisJoinPoint.getStaticPart().getSignature());
        System.out.println(
"Source Line: " + thisJoinPoint.getStaticPart().getSourceLocation());
        System.out.println(
"-----------------------------------------");        
    }

    
    
//Advice declaration
    before() : targetTypePatternAnotherClassPointcut() && !within(TargetRecipe+{
        System.out.println(
"---------- Aspect Advice Logic ----------");
        System.out.println(
"In the advice picked by targetTypePatternAnotherClassPointcut()");
        System.out.println(
"Join Point Kind" + thisJoinPoint.getKind());
        System.out.println(
"Type of executing object: " + thisJoinPoint.getThis().getClass().getName());
        System.out.println(
"Object referenced by this: " + thisJoinPoint.getThis());
        System.out.println(
"Signature: " + thisJoinPoint.getStaticPart().getSignature());
        System.out.println(
"Source Line: " + thisJoinPoint.getStaticPart().getSourceLocation());
        System.out.println(
"-----------------------------------------");        
    }


}



三. 捕获何时连接点的参数是某个数字、类型和次序
    使用args([Types|Identifiers])切入点。这个切入点的语法如下:
    pointcut <pointcut name>(<any value to be picked up>):args(<types> or <identifiers> | .. | *,<repeat>);

    args([Types|Identifiers])切入点具有8个关键特征:
        1.可以使用Types和Identifiers的任意组合来搜索到适当的连接点上,并把适当的环境展示给通知。
        2.Identifier用于检查运行时对象的类型,它们是捕捉的连接点处的参数,以及根据需要把这些对象展示给通知。
        3.使用..允许在一定程度上灵活地选择特定连接点处的参数数量,它们必须与args([Type|Identifier])声明匹配。
        4.如果不使用..,args([Type|Identifier])切入点就会选择与指定的类型精确匹配的所有连接点。这就是说:切入点只与在运行时其参数具有相同次序、数量和类型的方法上的连接点匹配。
如果使用..,切入点就会使用“最佳适配”策略。这意味着语句args(MyClass,..,float)将导致任何匹配的连接点都具有两个参数,它开始于一个MyClass对象,其后接着任意数量的参数,他们中间包括一个浮点数。
        5.在单个args([Type|Identifier])声明中只能使用一个..。
        6.使用*通配符允许在参数的类型方面表现处一定的灵活性,但是连接点的参数数量必须匹配。
            例如,如果在args([Type|Identifier])切入点声明中指定单个*,args(*),那么这个切入点将与具有一个任意类型参数的任何连接点匹配,并且会忽略没有参数的任何连接点。类似地,语句args(*,*)将匹配包含两个任意类型参数的任何连接点。
        7. 出现在字段访问中的连接点(通过get(TypePattern)切入点或set(TypePattern)切入点捕获)或者出现在静态类初始化中的连接点(通过staticinitialization(TypePattern)切入点捕获)没有要使用args([Types|Identifiers])切入点展示的任何参数。
        8. 如果把Object用作要被args([Types|Identifiers])切入点选择的标识符的类型,那么这将成功地匹配基本类型以及特定的Object实例。基本类型会自动“装箱”进其对应的对象类型中,例如,在把float基本类型传递给通知前,会将其“装箱”进Float中。这种行为提供了一种方法,可以通过它把基本参数值带到通知中。

    以下显示了args([Types|Identifiers])的两个示例
    1.当方法的参数是Identifier指定的MyClass对象时,捕获所有连接点
    2.当参数的类型是Type指定的AnotherClass时,捕获连接点

package com.aspectj;

public aspect ArgsRecipe {
    
/**
     * Specifies calling advice whenever the executing
     * object is of a type that matches the following rules:
     * 
     * Identifiers:MyClass object
     
*/

    pointcut argIdentifierMyClassPointcut(MyClass object):args(object);
    
/**
     * Specifies calling advice whenever the executing
     * object is of a type that matches the following rules:
     * 
     * Type Pattern:AnotherClass
     
*/
    
    pointcut argTypePatternAnotherClassPointcut():args(AnotherClass);
    
    
//Advice declaration
    before(MyClass object) : argIdentifierMyClassPointcut(object) && !within(ArgsRecipe+{
        System.out.println(
"---------- Aspect Advice Logic ----------");
        System.out.println(
"In the advice picked by argIdentifierMyClassPointcut()");
        System.out.println(
"Join Point Kind" + thisJoinPoint.getKind());
        System.out.println(
"this reference as passed by identifier " + object);
        System.out.println(
"Object referenced by this: " + thisJoinPoint.getThis());
        System.out.println(
"Signature: " + thisJoinPoint.getStaticPart().getSignature());
        System.out.println(
"Source Line: " + thisJoinPoint.getStaticPart().getSourceLocation());
        System.out.println(
"-----------------------------------------");        
    }

    
    
//Advice declaration
    before() : argTypePatternAnotherClassPointcut() && !within(ArgsRecipe+{
        System.out.println(
"---------- Aspect Advice Logic ----------");
        System.out.println(
"In the advice picked by argTypePatternAnotherClassPointcut()");
        System.out.println(
"Join Point Kind" + thisJoinPoint.getKind());
        System.out.println(
"Type of executing object: " + thisJoinPoint.getThis().getClass().getName());
        System.out.println(
"Object referenced by this: " + thisJoinPoint.getThis());
        System.out.println(
"Signature: " + thisJoinPoint.getStaticPart().getSignature());
        System.out.println(
"Source Line: " + thisJoinPoint.getStaticPart().getSourceLocation());
        System.out.println(
"-----------------------------------------");        
    }


}

posted on 2008-08-25 15:11 Brian 阅读(276) 评论(0)  编辑  收藏 所属分类: 《AspectJ Cookbook》读书笔记


只有注册用户登录后才能发表评论。


网站导航:
 

公告


导航

<2008年8月>
272829303112
3456789
10111213141516
17181920212223
24252627282930
31123456

统计

常用链接

留言簿(4)

随笔分类

随笔档案

收藏夹

搜索

最新评论

阅读排行榜

评论排行榜