最爱Java

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

一.继承切入点定义
        创建一个抽象类。使用合适的public、protected或default访问修饰符在抽象方面内定义可重用的切入点逻辑。最后,把抽象方面继承进子方面中,以重用声明的切入点。

package com.aspectj;

public abstract aspect BasePointcutDefinitionsAspect {
    
public pointcut callPointcut() : call(void MyClass.foo(int,String));
}

 

package com.aspectj;

public aspect ReusePointcutsRecipe extends BasePointcutDefinitionsAspect {
    
//Advice declaration
    before():callPointcut()&&!within(ReusePointcutsRecipe+{
        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(
"-----------------------------------------");        
    }

}




二.实现抽象切入点
        在声明切入点和周围的方面时,使用abstract关键字,并且不要提供任何切入点逻辑。

package com.aspectj;

public abstract aspect BaseAbstractAspect {
    
/**
     * Specifies an abstract pointcut placeholder
     * for derived aspects to specify
     
*/

    
public abstract pointcut abstractBasepointcut();
    
    
/**
     * Specifies calling advice whenever a join point
     * picked by the abstractBasePointcut (specified
     * by specialized aspects) is encountered, and not within
     * this aspect or any inheriting aspects.
     
*/

    pointcut runAdvicePointcut() : abstractBasepointcut() 
&& !within(BaseAbstractAspect+);
}

 

package com.aspectj;

public aspect AbstractImplementationAspect extends BaseAbstractAspect {
    
/**
     * Specifies calling advice whenever a method
     * matching the following rules gets called:
     * 
     * Class Name: MyClass
     * Method Name:foo
     * Method Return:void
     * Method Parameters:an int followed by a string
     
*/

    
public pointcut abstractBasepointcut():call(void MyClass.foo(int,String));
    
    
//Advice declaration
    before():runAdvicePointcut(){
        System.out.println(
"---------- Aspect Advice Logic ----------");
        System.out.println(
"Signature: " + thisJoinPoint.getStaticPart().getSignature());
        System.out.println(
"Source Location: " + thisJoinPoint.getStaticPart().getSourceLocation());
        System.out.println(
"-----------------------------------------");            
    }


}


三.把类继承进方面中
    使用extends关键字来声明方面扩展类。示例为一个伪日志记录类,它代表一种现有的日志记录机制。其目标是:重构对应用程序中日志记录类的所有现有的调用,并把日志记录模块化进一个方面中,它可以更灵活地织入进应用程序中。

package com.aspectj;

public class OOLogging {
    
public void logEntry(String entry) {
        System.out.println(
"Entry logged: " + entry);
    }

}

 

package com.aspectj;

public aspect AOLogging extends OOLogging{
    
/**
     * Specifies calling advice whenever a method
     * matching the following rules gets called:
     * 
     * Class Name: MyClass
     * Method Name:foo
     * Method Return:void
     * Method Parameters:an int followed by a string
     
*/

    pointcut callPointcut() : call(
void MyClass.foo(int,String));
    
    
//Advice declaration
    before():callPointcut()&&!within(AOLogging+)&&!within(AOLogging) {
        
this.logEntry(thisJoinPoint.toShortString());
    }

}


 

posted @ 2008-08-26 15:34 Brian 阅读(270) | 评论 (0)编辑 收藏

一. 定义单件(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 @ 2008-08-26 14:37 Brian 阅读(450) | 评论 (0)编辑 收藏
     摘要: 一.访问类成员  package com.aspectj; public privileged aspect MemberAccessRecipe {     /** *//**      * Specifies&nb...  阅读全文
posted @ 2008-08-26 13:45 Brian 阅读(1545) | 评论 (1)编辑 收藏
     摘要: 一.捕获何时连接点上的运行时条件评估为true     使用if(Expression)语句来评估包含要比较的运行时变量的布尔表达式。if(Expression)语句的语法如下:     pointcut <pointcut name>(<any values to be picked up>...  阅读全文
posted @ 2008-08-25 20:40 Brian 阅读(405) | 评论 (0)编辑 收藏
     摘要:          this([Type | Identifier])研究的是在捕捉的连接点处由this引用的对象的类型。连接点的目标(通过target([Type | Identifier])切入点指定)依赖于连接点类型而有所不同,但它常常是在其上调用方法的对象,或者是以某种方式访问的在其中遇到连接点的属性。...  阅读全文
posted @ 2008-08-25 15:11 Brian 阅读(276) | 评论 (0)编辑 收藏

    本章中描述的切入点支持捕获另一个初始连接点作用域或环境内的所有连接点。每个连接点在程序的控制流程中都有一个具体位置,这为通过这里描述的切入点声明捕获的连接点提供了环境。
    一. 捕获通过初始连接点开始的程序控制流程内的所有连接点
    使用cflow(Pointcut)切入点。cflow(Pointcut)切入点的语法如下:
    pointcut <pointcut name>(<any values to be picked up>) : cflow(<pointcut>);

    cflow(Pointcut)切入点具有3个关键特征:
        1.cflow(Pointcut)切入点捕获在初始特定的连接点环境内遇到的所有连接点,这个初始连接点是通过另一个切入点选择的。
        2.捕获的连接点包括初始连接点。
        3.作用域是cflow(pointcut)切入点中重要的鉴别器。这个切入点将捕获通过切入点参数捕获的连接点的控制流程内的所有连接点。


package com.aspectj;

public aspect CFlowRecipe {
    
/**
     * 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 callInitialPointcut():call(
void MyClass.foo(int,String));
    
    
/**
     * Specifies calling advice whenever a join point is encountered
     * including and after the initial join point triggers the pointcut
     * that is specified in the parameter:
     * 
     * Pointcut Name:callInitialPointcut
     
*/

    pointcut cflowPointcut():cflow(callInitialPointcut());
    
    
//Advice declaration
    before() : cflowPointcut() && !within(CFlowRecipe+{
        System.out.println(
"---------- Aspect Advice Logic ----------");
        System.out.println(
"In the advice picked by CFlowRecipe()");
        System.out.println(
"Join Point Kind: " + thisJoinPoint.getKind());
        System.out.println(
"Signature: " + thisJoinPoint.getStaticPart().getSignature());
        System.out.println(
"Source Line: " + thisJoinPoint.getStaticPart().getSourceLocation());
        System.out.println(
"-----------------------------------------");
    }
    
    

}



        值得更详细研究cflow(Pointcut)做什么。这个特殊的切入点引入了连接点环境的概念。它是指每个连接点具有一个作用域,在这个用途域内,它被看成是执行程序的控制流程的一部分。
        在这个控制流程内,任何遇到的连接点都会触发cflow(Pointcut)切入点,并调用任何关联的通知。当初始连接点触发指定的切入点参数时,cflow(Pointcut)切入点会起作用,并触发其关联的通知。然后,将为在初始连接点环境内的控制流程中遇到的每个连接点调用与cflow(Pointcut)关联的通知。最后,捕获的连接点集合包括初始连接点本身,这就是这个切入点与cflowbelow(Pointcut)切入点之间的主要区别。

        在cflow(Pointcut)的当前实现中,在使用它时,其实现方式会引入大量的系统开销。在可能的地方,并且连接点重用不受影响时,可以考虑优先使用withincode(Signature)切入点。

    二.捕获程序控制流程内的所有连接点,不包括初始连接点
    使用cflowbelow(Pointcut)切入点。cflowbelow(Pointcut)切入点的语法如下:
    pointcut <pointcut name>(<any values to be picked up>) : cflowbelow(<pointcut>);


package com.aspectj;

public aspect CFlowBelowRecipe {
    
/**
     * 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 callInitialPointcut():call(
void MyClass.foo(int,String));
    
    
/**
     * Specifies calling advice whenever a join point is encountered
     * after the initial join point triggers the pointcut
     * that is specified in the parameter:
     * 
     * Pointcut Name:callInitialPointcut
     
*/

    pointcut cflowPointcut():cflowbelow(callInitialPointcut());
    
    
//Advice declaration
    before() : cflowPointcut() && !within(CFlowBelowRecipe+{
        System.out.println(
"---------- Aspect Advice Logic ----------");
        System.out.println(
"In the advice picked by CFlowBelowRecipe()");
        System.out.println(
"Join Point Kind: " + thisJoinPoint.getKind());
        System.out.println(
"Signature: " + thisJoinPoint.getStaticPart().getSignature());
        System.out.println(
"Source Line: " + thisJoinPoint.getStaticPart().getSourceLocation());
        System.out.println(
"-----------------------------------------");
    }
    
    

}



    这里和第一部分介绍的内容有点区别;其区别是实际捕获的连接点数量。cflow(Pointcut)切入点会触发在初始连接点环境内遇到的所有连接点(包括初始连接点)上的通知,而cflowbelow(Pointcut)切入点则不包括那个初始连接点。

posted @ 2008-08-25 10:36 Brian 阅读(412) | 评论 (0)编辑 收藏

    切入点定义设计中的常用方式是:基于关注的程序作用域,限制捕获连接点的范围。这可以让你即使控制在进一步的切入点定义中将会涉及哪些连接点。
    本章中的切入点相当容易理解,并且他们是AspectJ中一些常用的元素。例如,广泛使用的within(TypePattern)切入点将以!within(%THIS_ASPECT%)形式使用它。这个AspectJ术语限制了当前方面之外的每个连接点的作用域,从而可以防止通知触发对相同通知块的递归调用,并导致一个无限循环。
    一. 捕获特定类中的所有连接点
    使用within(TypePattern)切入点,利用TypePattern指定特定类类型模式,within(TypePattern)切入点的语法如下:
    pointcut <pointcut name>(<any values to be picked up>) : within(<class>);

    within(TypePattern)切入点具有3个关键特征:
        1.within(TypePattern)切入点捕获指定类作用域中的所有连接点。
        2.within(TypePattern)切入点极少孤立使用。相反,它通常与切入点结合使用,用于减少将触发附带通知的连接点。
        3.TypePattern可以包含通配符,用于选择不同类上的一系列连接点。


 

 

package com.aspectj;

public aspect WithinClassRecipe {
    
/**
     * Specifies calling advice on any join point encountered within
     * the defined scope:
     * 
     * Scope:MyClass
     
*/

    pointcut withinMyClass() : within(MyClass);
    
    
//Advice declaration
    before() : withinMyClass() && !within(WithinClassRecipe+{
        System.out.println(
"---------- Aspect Advice Logic ----------");
        System.out.println(
"In the advice picked by withinMyClass()");
        System.out.println(
"Join Point Kind: " + thisJoinPoint.getKind());
        System.out.println(
"Signature: " + thisJoinPoint.getStaticPart().getSignature());
        System.out.println(
"Source Line: " + thisJoinPoint.getStaticPart().getSourceLocation());
        System.out.println(
"-----------------------------------------");
    }


}



二. 捕获特定包中的所有连接点
    within(TypePattern)切入点提供一种有用的手段,它使用通配符在出现在每个类中的连接点中指定一个关注。可以在TypePattern中使用合适的通配符,从切入点逻辑的余下部分中包含或排除连接点的整个包。

package com.aspectj;

public aspect WithinPackageRecipe {
    
/**
     * Specifies calling advice on any join point encountered within
     * the defined scope:
     * 
     * Scope:packageA
     
*/

    pointcut withinPackageA() : within(packageA.
*);
    
    
//Advice declaration
    before() : withinPackageA() && !within(WithinPackageRecipe+{
        System.out.println(
"---------- Aspect Advice Logic ----------");
        System.out.println(
"In the advice picked by WitinPackageRecipe()");
        System.out.println(
"Join Point Kind: " + thisJoinPoint.getKind());
        System.out.println(
"Signature: " + thisJoinPoint.getStaticPart().getSignature());
        System.out.println(
"Source Line: " + thisJoinPoint.getStaticPart().getSourceLocation());
        System.out.println(
"-----------------------------------------");
    }


}


 

三. 捕获特定方法内的所有连接点
    使用withincode(Signature)切入点。withincode(Signature)切入点的语法如下:
    pointcut <pointcut name>(<any values to be picked up>) : withincode(<modifier> <class>.<method>(<paramter types>));

    withincode(Signature)切入点有3个关键特征:
        1. withincode(Signature)切入点指定了特定方法的本地作用域内的所有连接点。
        2. withincode(Signature)切入点极少孤立使用。相反,他通常与其他切入点结合使用,用于减少将触发附带通知的连接点。
        3. Signaure可以包含通配符,用于选择不同类的不同方法上的一系列连接点。

package com.aspectj;

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

    pointcut withinFooIntStringAnyReturnPointcut() : withincode(
* MyClass.foo(int,String));
    
    
//Advice declaration
    before() : withinFooIntStringAnyReturnPointcut() && !within(WithinMethodRecipe+{
        System.out.println(
"---------- Aspect Advice Logic ----------");
        System.out.println(
"In the advice picked by withinMyClass()");
        System.out.println(
"Join Point Kind: " + thisJoinPoint.getKind());
        System.out.println(
"Signature: " + thisJoinPoint.getStaticPart().getSignature());
        System.out.println(
"Source Line: " + thisJoinPoint.getStaticPart().getSourceLocation());
        System.out.println(
"-----------------------------------------");
    }


}

posted @ 2008-08-25 10:32 Brian 阅读(322) | 评论 (0)编辑 收藏

一. 捕获何时访问对象的属性
    使用get(Signature)切入点。get(Signature)切入点的语法如下:
    pointcut <pointcut name>(<any values to be picked up>) : get(<optional modifier> <type> <class>.<field>);
    get(Signature)具有4个关键特征:
    1.get(Signature)切入点会触发直接在其中(而不仅仅是在访问器方法的调用上)访问属性的通知。
    2.get(Signature)切入点不能捕获对静态属性的访问,尽管从AspectJ的语法角度讲以这种方式定义切入点是完全合法的。
    3.Signature必须解析成特定类的属性。
    4.Signature可以包含通配符,用于选择不同属性上的一系列连接点。

package com.aspectj;

public aspect GetRecipe {
    
/**
     * Specifies calling advice whenever an attribute matching the following rules
     * is accessed:
     * 
     * Type:String 
     * Class Name:MyClass 
     * Attribute Name:name
     
*/

    pointcut getNamePointcut(): get(String MyClass.name);
    
    
// Advice declaration
    before():getNamePointcut() {
        System.out.println(
"---------- Aspect Advice Logic ----------");
        System.out.println(
"In the advice picked by getNamePointcut()");
        System.out.println(
"Signature: " + thisJoinPoint.getSignature());
        System.out.println(
"Source Line: " + thisJoinPoint.getSourceLocation());
        System.out.println(
"-----------------------------------------");
    }

}

    你可能期待类使用static和final关键字定义一个常量属性,这样,在访问这个常量时你就可能使用get(Signature)切入点来捕获。
    

package com.aspectj;

public aspect GetConstant {
    
/**
     * Specifies calling advice whenever an attribute matching the following rules
     * is accessed:
     * 
     * Type:String 
     * Class Name:MyClass 
     * Attribute Name:CONSTANT
     
*/

    pointcut getConstantPointcut():get(
public static final String MyClass.CONSTANT);
    
    
//Advice declaration
    before():getConstantPointcut() {
        System.out.println(
"---------- Aspect Advice Logic ----------");
        System.out.println(
"In the advice picked by getConstantPointcut()");
        System.out.println(
"Signature: " + thisJoinPoint.getSignature());
        System.out.println(
"Source Line: " + thisJoinPoint.getSourceLocation());
        System.out.println(
"-----------------------------------------");        
    }

}

 

二. 捕获访问的字段值
    使用after returning(<ReturnValue>)形式的通知。它在声明的returning()部分中带有一个标识符,用于包含访问过的值。

package com.aspectj;

public aspect CaptureAccessedFieldValue {
    pointcut getNamePointcut() : get(String MyClass.name);
    
    
//Advice declaration
    after() returning(String value) : getNamePointcut() {
        System.out.println(
"---------- Aspect Advice Logic ----------");
        System.out.println(
"In the advice picked by getNamePointcut()");
        System.out.println(
"Signature: " + thisJoinPoint.getStaticPart().getSignature());
        System.out.println(
"Source Line: " + thisJoinPoint.getStaticPart().getSourceLocation());
        System.out.println(
"-----------------------------------------");        
    }

}


三. 捕获何时修改对象的字段
    使用set(Signature)切入点。set(Signature)切入点的语法如下:
    pointcut <pointcut name>(<any values to be picked up>) : set(<optional modifier> <type> <class>.<field>);
    
    set(Signature)具有4个关键特征:
    1.set(Signature)切入点在修改字段时触发。
    2.set(Signature)切入点不能捕获对静态字段的修改,尽管从AspectJ的语法角度讲以这种方式定义切入点是完全合法的。
    3.Signature必须解析成特定类的属性。
    4.Signature可以包含通配符,用于选择不同属性上的一系列连接点。

package com.aspectj;

public aspect SetRecipe {
    
/*
     * Specifies calling advice whenever an attribute
     * matching the following rules is modified:
     * 
     * Type: String
     * Class Name: MyClass
     * Attribute: name
     
*/

    pointcut setNamePointcut() :set(String MyClass.name);
    
    
//Advice declaration
    before():setNamePointcut() && !within(SetRecipe+{
        System.out.println(
"---------- Aspect Advice Logic ----------");
        System.out.println(
"In the advice picked by setNamePointcut()");
        System.out.println(
"Signature: " + thisJoinPoint.getSignature());
        System.out.println(
"Source Line: " + thisJoinPoint.getSourceLocation());
        System.out.println(
"-----------------------------------------");        
    }

}

 

四. 在修改字段时捕获它的值
    结合使用args([Types | Identifiers])切入点和set(Signature)切入点,展示字段的新值,该字段被设置成切入点上的标识符,可将其传递给相应的通知。

package com.aspectj;

public aspect CaptureModifiedFieldValue {
    pointcut setNamePointcut(String newValue):set(String MyClass.name) 
&& args(newValue);
    
    
//Advice declaration
    before(String newValue) : setNamePointcut(newValue) {
        System.out.println(
"---------- Aspect Advice Logic ----------");
        System.out.println(
"In the advice picked by setNamePointcut()");
        System.out.println(
"Signature: " + thisJoinPoint.getSignature());
        System.out.println(
"Source Line: " + thisJoinPoint.getSourceLocation());
        System.out.println(
"-----------------------------------------");                
    }

}

posted @ 2008-08-22 10:43 Brian 阅读(1166) | 评论 (0)编辑 收藏

一.  捕获对构造函数的调用
    使用Call(Signature)写入点,它带有额外的new关键字作为签名的一部分。使用与构造函数有关的call(Signature)切入点的语法如下:
    pointcut <pointcut name>(<any values to be picked up>): call(<optional modifier> <class>.new(<parameter types>));

    在用于捕获对构造函数的调用时,call(Signature)切入点具有3个关键特征:
    1.在把一个类实例化成一个对象时,具有new关键字的call(Signature)切入点会捕获连接点。
    2.通过使用around()形式的通知,call(Signature)写入点可以在Java的正常继承规则的限制下重写返回对象的类型。
    3.编译器不会检查指定的Signature是否对应于实际的构造函数。

 

package com.aspectj;

public aspect CallNewRecipe {
    
/*
     * Specifies calling advice when any constructor is called
     * that meets the following signature rules:
     * 
     * Class Name:MyClass
     * Method Name:new (This is a keyword indicating the constructor call)
     * Method Parameters: int , String
     
*/

    pointcut myClassConstructorWithIntAndStringPointcut() : call(MyClass.
new(int , String));
    
    
//Advice declaration
    before() : myClassConstructorWithIntAndStringPointcut() {
        System.out.println(
"---------- Aspect Advice Logic ----------");
        System.out.println(
"In the advice picked by myClassConstructorWithIntAndOthersPointcut()");
        System.out.println(
"The current type of object under construction is:");
        System.out.println(thisJoinPoint.getThis());
        System.out.println(
"Signature: " + thisJoinPoint.getSignature());
        System.out.println(
"Source Line: " + thisJoinPoint.getSourceLocation());
        System.out.println(
"-----------------------------------------");
    }

}



二. 在执行构造函数时捕获它
    使用execution(Signature)切入点,它带有额外的new关键字作为签名的一部分。使用与构造函数有关的execution(Signature)切入点的语法如下:
    pointcut <pointcut name>(<any values to be picked up>):execution(<optional modifier> <class>.new<parameter types>));

    在用于捕获构造函数的执行时,execution(Signature)切入点具有3个关键特征:
    1.在执行类的构造函数时,具有new关键字的execution(Signature)切入点会触发连接点。
    2.不能在调用类的构造函数之前那一刻触发连接点。这会阻止重写返回的对象。
    3.可以使用around()通知来重写构造函数方法的实现,当不能重写正在构造的对象的类型。


package com.aspectj;

public aspect ExecutionNewRecipe {
    
/*
     * Specifies calling advice when any constructor executes
     * that meets the following signature rules:
     * 
     * Class Name:MyClass
     * Method Name:new (This is a keyword indicating the constructor call)
     * Method Parameters: int , String
     
*/

    pointcut myClassConstructorWithIntAndStringPointcut() : execution(MyClass.
new(int,String));
    
    
//Advice declaration
    before() : myClassConstructorWithIntAndStringPointcut() {
        System.out.println(
"---------- Aspect Advice Logic ----------");
        System.out.println(
"In the advice picked by myClassConstructorWithIntAndOthersPointcut()");
        System.out.println(
"The current type of object under construction is:");
        System.out.println(thisJoinPoint.getThis().getClass());
        System.out.println(
"Signature: " + thisJoinPoint.getSignature());
        System.out.println(
"Source Line: " + thisJoinPoint.getSourceLocation());
        System.out.println(
"-----------------------------------------");        
    }

}


三. 捕获何时初始化对象
    使用initialization(Signature)切入点。initialization(Signature)切入点的语法如下:
    pointcut <pointcut name>(<any values to be picked up>):initialization(<optional modifier> <class>.new<parameter types>));

    initialization(Signature)切入点具有5个关键特征:
    1.initialization(Signature)切入点必须包含new关键字。
    2.initialization(Signature)切入点捕获连接点发生在任何超类的初始化之后,以及从构造函数方法返回之前。
    3.Signature必须解析成特定类的构造函数,而不是一个简单的方法。
    4.initialization(Signature)切入点提供了编译时的检查,用于检查构造函数是否正在被引用。
    5.由于AspectJ编译器中的编译器限制,当与around()通知关联时,不能使用initialization(Signature)切入点。

 

package com.aspectj;


public aspect InitializationRecipe {
    
/*
     * Specifies calling advice when any object
     * initializes using a constructor
     * that meets the following signature rules:
     * 
     * Class Name:MyClass
     * Method Name:new (This is a keyword indicating the constructor call)
     * Method Parameters: int and any others
     
*/

    pointcut myClassObjectInitializationWithIntAndStringPointcut() : execution(MyClass.
new(int,*));
    
    
//Advice declaration
    before() : myClassObjectInitializationWithIntAndStringPointcut() {
        System.out.println(
"---------- Aspect Advice Logic ----------");
        System.out.println(
"In the advice picked by myClassObjectInitializationWithIntAndStringPointcut()");
        System.out.println(
"The current type of object under construction is:");
        System.out.println(thisJoinPoint.getThis().getClass());
        System.out.println(
"Signature: " + thisJoinPoint.getSignature());
        System.out.println(
"Source Line: " + thisJoinPoint.getSourceLocation());
        System.out.println(
"-----------------------------------------");        
    }

}



四. 捕获何时将要初始化一个对象
    使用preinitialization(Signature)切入点。preinitialization(Signature)切入点的语法如下:
    pointcut <pointcut name>(<any values to be picked up>):preinitialization(<optional modifier> <class>.new<parameter types>));

    preinitialization(Signature)切入点具有5个关键特征:
    1.preinitialization(Signature)切入点必须包含new关键字。
    2.preinitialization(Signature)切入点捕获连接点发生在进入捕获构造函数之后,以及调用任何超类构造函数之前。
    3.Signature必须解析成一个构造函数。
    4.preinitialization(Signature)切入点提供了编译时的检查,用于检查构造函数是否正在被引用。
    5.由于AspectJ编译器中的编译器限制,当与around()通知关联时,不能使用preinitialization(Signature)切入点。

 

package com.aspectj;

public aspect PreInitializationRecipe {
    
/*
     * Specifies calling advice just before an object initializes
     * using a constructor that meets the following signature rules:
     * 
     * Class Name:MyClass
     * Method Name:new (This is a keyword indicating the constructor call)
     * Method Parameters: an int followed by a String
     
*/

    pointcut myClassIntStringObjectPreInitializationPointcut() : preinitialization(MyClass.
new(int,String));
    
    
//Advice declaration
    before(int number , String name) : myClassIntStringObjectPreInitializationPointcut() && args(number , name) {
        System.out.println(
"---------- Aspect Advice Logic ----------");
        System.out.println(
"In the advice picked by anyMyClassObjectInitializationPointcut()");
        System.out.println(
"The current type of object under construction is:");
        System.out.println(thisJoinPoint.getThis());
        System.out.println(
"The values passed in where: " + number + " , " + name);
        System.out.println(
"Signature: " + thisJoinPoint.getSignature());
        System.out.println(
"Source Line: " + thisJoinPoint.getSourceLocation());
        System.out.println(
"-----------------------------------------");        
    }

}



五. 捕获何时初始化类
    使用staticinitialization(TypePattern)写入点。staticinitialization(TypePattern)写入点的语法如下:
    pointcut <pointcout name>(<any values to be picked up>) : staticinitialization(<class>);

    staticinitialization(TypePattern)切入点具有两个关键特征:
    1.对可供staticinitialization(TypePattern)切入点所选通知使用的环境有一些限制。没有父对象触发静态初始化;因此,没有this引用。也不涉及实例对象,因此,没有目标引用。
    2.TypePattern可以包含通配符,用于选择一系列不同的类。

package com.aspectj;

public aspect StaticinitializationRecipe {
    
/*
     * Specifies calling advice when a class is initialized
     * that meets the following type pattern rules:
     * 
     * Class Name:MyClass
     
*/

    pointcut myClassStaticInitializationPointcut() : staticinitialization(MyClass);
    
    
//Advice declaration
    before() : myClassStaticInitializationPointcut() {
        System.out.println(
"---------- Aspect Advice Logic ----------");
        System.out.println(
"In the advice picked by myClassStaticInitializationPointcut()");
        System.out.println(
"Join Point Kind: ");
        System.out.println(thisJoinPoint.getStaticPart().getKind());
        System.out.println(
"Signature: " + thisJoinPoint.getSignature());
        System.out.println(
"Source Line: " + thisJoinPoint.getSourceLocation());
        System.out.println(
"-----------------------------------------");        
    }

}

posted @ 2008-08-22 10:32 Brian 阅读(1211) | 评论 (0)编辑 收藏

    在Java中抛出异常时,会将其向上传递给调用者,直到它被作为try/catch块一部分的catch语句处理或者到达Java运行库并在控制台引发一条混乱的消息。如果捕获到异常,就应该将异常作为一个对象传递给catch块做合适的处理。同时,还有一种可能需要方面作为横切行为做一部分事情,或者替代catch块的正常行为。
一. 捕获何时捕捉异常
    使用handler(TypePattern)切入点。其语法如下:
    pointcut <pointcut name>(<any values to be picked up>) : handler(<class>):
 
   handler(TypePattern)切入点具有5个关键特征:
   1. handler(TypePattern)在捕获异常的作用域内选择连接点。
   2. handler(TypePattern)切入点的通知仅用于类型模式指定Throwable或其子类的地方。
   3. TypePattern声明无论何时捕捉到异常或其子类的匹配模式,都会应用相应的通知。
   4. handler(TypePattern)切入点只支持before()形式的通知。这意味着不能使用像around()这样的通知来重写catch块的正常行为。
   5. TypePattern可以包含通配符,用于选择不同类上的一系列连接点。
带有通配符的TypePattern 描述
mypackage..* 捕获mypackage包及其子包中的连接点类
MyClass+ 捕获MyClass类及其任何子类中的连接点

    下面的例子展示了捕获任何类抛出MyException类异常:

package com.aspectj;

public aspect HandlerRecipe {
    
/**
     * Specifies calling advice when any exception object
     * is caught that matches the following rules for its 
     * type pattern;
     * 
     * Type:MyException
     
*/

    pointcut myExceptionHandlerPointcut() : handler(MyException);
    
    
//Advice declaration
    before() : myExceptionHandlerPointcut() {
        System.out.println(
"------------------- Aspect Advice Logic -------------------");
        System.out.println(
"In the advice picked by " + "myExceptionHandlerPointcut()");
        System.out.println(
"Signature: " + thisJoinPoint.getStaticPart().getSignature());
        System.out.println(
"Source Line: " + thisJoinPoint.getStaticPart().getSourceLocation());
        System.out.println(
"------------------------------------------");
    }

}


二. 捕获抛出的异常
    结合使用args([Types | Identifiers])切入点 与handler(TypePattern)切入点,将捕获的异常展示为切入点上的标识符,可将其传递给相应的通知。
package com.aspectj;

public aspect AccessThrownException {
    pointcut myExceptionHandlerPointout(MyException exception) : handler(MyException) 
&& args(exception);
    
    
//Advice declaration
    before(MyException exception) : myExceptionHandlerPointout(exception) {
        System.out.println(
"------------------- Aspect Advice Logic -------------------");
        System.out.println(
"In the advice picked by " + "myExceptionHandlerPointcut()");
        System.out.println(
"Signature: " + thisJoinPoint.getStaticPart().getSignature());
        System.out.println(
"Source Line: " + thisJoinPoint.getStaticPart().getSourceLocation());
        System.out.println(
"Exception caught:");
        exception.printStackTrace();
        System.out.println(
"------------------------------------------");
    }

}
   
posted @ 2008-07-11 09:28 Brian 阅读(1597) | 评论 (1)编辑 收藏
仅列出标题
共5页: 上一页 1 2 3 4 5 下一页 

公告


导航

<2024年5月>
2829301234
567891011
12131415161718
19202122232425
2627282930311
2345678

统计

常用链接

留言簿(4)

随笔分类

随笔档案

收藏夹

搜索

最新评论

阅读排行榜

评论排行榜