最爱Java

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

《AspectJ Cookbook》读书笔记十四: 定义方面实例化

一. 定义单件(singleton)方面
        通过把issingleton()语句显示添加到方面声明中,来显示建立单件方面实例化策略。

 

package com.aspectj;

public aspect Singleton issingleton() {
    
/**
     * Specifies calling advice whenever a method 
     * matching the following rules gets called:
     * 
     * Class Name: MyClass
     * Method Name:foo
     * Method Return Type:void
     * Method Parameters:an int followed by a String
     
*/

    pointcut callPointCut() : call(
void MyClass.foo(int,String));
    
    
//Advice declartion
    before():callPointCut() && !within(Singleton+{
        System.out.println(
"---------- Aspect Advice Logic ----------");
        System.out.println(
"In the advice attached to the call point cut");
        System.out.println(
"Target: " + thisJoinPoint.getTarget());
        System.out.println(
"This: " + thisJoinPoint.getThis());
        System.out.println(
"Aspect Instance: " + Singleton.aspectOf());
        System.out.println(
"-----------------------------------------");        
    }

}


        传统的面向对象单件的主要缺点是:使用单件的每个类都与单件的公共接口紧密耦合。而面向方面的单件没有这个缺点。

二.在每个实例上定义一个方面
        AspectJ提供了perthis(Pointcut)和pertarget(Pointcut)方面实例化策略,他们依据Pointcut定义选择的类,来声明应该为每个新的对象实例所实例化的方面。
        perthis(Pointcut)声明和pertarget(Poinitcut)声明之间的区别必须涉及:在到达通知的连接点时,将会检查什么对象。perthis(Pointcut)声明指定:将为通知触发连接点处的this说引用的每个新对象而实例化一个新的方面。pertarget(Pointcut)实例化策略指定:如果新对象是通知触发连接点的目标,则为每个这样的新对象实例化一个新的方面。

 

package com.aspectj;

public aspect PerThis perthis(callPointCut()) {
    
/**
     * Specifies calling advice whenever a method matching the following rules
     * gets called:
     * 
     * Class Name: MyClass Method Name:foo Method Return Type:void Method
     * Parameters:an int followed by a String
     
*/

    pointcut callPointCut() : call(
void MyClass.foo(int,String));

    
// Advice declaration
    before():callPointCut()&&!within(PerThis+){
        System.out.println(
"---------- Aspect Advice Logic ----------");
        System.out.println(
"In the advice attached to the call point cut");
        System.out.println(
"Target: " + thisJoinPoint.getTarget());
        System.out.println(
"This: " + thisJoinPoint.getThis());
        System.out.println(
"Aspect Instance: " + PerThis.aspectOf(thisJoinPoint.getThis()));
        System.out.println(
"-----------------------------------------");
    }

}


        在考虑可以通过单个方面通知多个类时,perthis(Pointcut)和pertarget(Pointcut)方面实例化策略声明上的Pointcut参数提供了一些有趣的问题。以下示例中perthis(Pointcut)方面实例化策略只与executeMyClass()切入点指定的MyClass类的对象相关。

 

package com.aspectj;

public aspect AdviseMultipleClasses perthis(executeMyClassFoo()){
    
public pointcut executeMyClassFoo() : execution(void MyClass.foo());
    
    
public pointcut executeAnotherClassFoo() : execution(void AnotherClass.foo());
    
    before():executeMyClassFoo() 
{
        System.out.println(
"Advising foo");
        System.out.println(
"Aspect is: " + this);
    }

    
    before():executeAnotherClassFoo() 
{
        System.out.println(
"Advising foo");
        System.out.println(
"Aspect is: " + this);
    }

}


        声明只为executeMyClassFoo()切入点指定的每个新对象实例化AdviseMultipleClasses方面,这隐式排除了其他类的对象。即使声明了executeAnotherClassFoo()切入点,并且他具有相应的通知,也不会导致把任何方面应用于除了它与executeMyClassFoo()共享的那些类之外的任何类。在示例中,两个切入点之间没有共享任何公共类,因此,executeMyClassFoo()切入点及关联的通知会被忽略,因为这个切入点参与了perthis(Pointcut)实例化策略的定义。

        一个方面不能具有针对两类不同对象的两种实例化策。为了确保方面的实例化策略与它通知的类的素有对象相关,一种有用的技术是:纯粹为了使用方面的实例化策略,声明一个切入点来结合方面中的所有其他的切入点声明,如:

 

package com.aspectj;

public aspect AdviseMultipleClasses perthis(executeMyClassFoo()){
    
public pointcut executeMyClassFoo() : execution(void MyClass.foo());
    
    
public pointcut executeAnotherClassFoo() : execution(void AnotherClass.foo());
    
    
public pointcut applyLifecyclePolicy() : executeMyClassFoo()||executeAnotherClassFoo();
    
    before():executeMyClassFoo() 
{
        System.out.println(
"Advising foo");
        System.out.println(
"Aspect is: " + this);
    }

    
    before():executeAnotherClassFoo() 
{
        System.out.println(
"Advising foo");
        System.out.println(
"Aspect is: " + this);
    }

}


三.在每个控制流程上定义一个方面
        使用percflow(Pointcut)方面实例化声明。percflow(Pointcut)语句指示编译器,它应该为从Pointcut参数指定的连接点集合内进入的每个新控制流程创建方面的一个新实例。

package com.aspectj;

public aspect PerControlFlow percflow(callPointCut()){
    
/**
     * Specifies calling advice whenever a method matching the following rules
     * gets called:
     * 
     * Class Name: MyClass Method Name:foo Method Return Type:void Method
     * Parameters:an int followed by a String
     
*/

    pointcut callPointCut() : call(
void MyClass.foo(int,String));

    
// Advice declaration
    before():callPointCut()&&!within(PerControlFlow+){
        System.out.println(
"---------- Aspect Advice Logic ----------");
        System.out.println(
"In the advice attached to the call point cut");
        System.out.println(
"Target: " + thisJoinPoint.getTarget());
        System.out.println(
"This: " + thisJoinPoint.getThis());
        System.out.println(
"Aspect Instance: " + PerControlFlow.aspectOf());
        System.out.println(
"-----------------------------------------");
    }

}


percflow(Pointcut)语句代表最细粒度的方面实例化策略,并且会为特定的代码段创建最大苏联高的不同方面实例。

posted on 2008-08-26 14:37 Brian 阅读(449) 评论(0)  编辑  收藏 所属分类: 《AspectJ Cookbook》读书笔记


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


网站导航:
 

公告


导航

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

统计

常用链接

留言簿(4)

随笔分类

随笔档案

收藏夹

搜索

最新评论

阅读排行榜

评论排行榜