AspectJ学习(2)使用切入点 target和this

AspectJ学习(2)使用切入点 target和this

        target 切入点格式如下: target ([ Type | Identifier ])。 Type 指示对连接点处的对象类型提供一个静态编译时评估,并采用完全限定类名的形式(也就是说, Type 不能是使用通配符的类型声明模式)。 Identifier 提供了一种方法,可通过它来评估连节点处的运行时对象的实际类型,而不仅仅是静态类型。 Identifier 在运行时动态地赋予合适的对象。

        下面通过例子说明一下 target 的使用:

public interface Animal {

    void speak();

}


public class Cat implements Animal{

    public void speak() {

        System. out .println( " 喵喵 " );

    }

}


public class Dog implements Animal{

    public void speak() {

        System. out .println( " 汪汪 " );

    }

}

public class Zoo {

    private List<Animal> animals = new ArrayList<Animal>();

    public void addAnimal(Animal a){

        animals .add(a);

    }

    public void speak(){

        for (Animal a : animals ){

                a.speak();

        }

    }

}

   

定义一个切入点如下:

public pointcut speakCallOne():

    call (* speak()) && target (Animal);

        虽然 pointcut speakCallOne() 中的 call (* speak()) 匹配所有类的 speak() 方法(这里匹配 Cat 、 Dog 、 Zoo ),但 target (Animal) 便将 pointcut speakCallOne() 限定在 Animal 及其子类(也就是 Cat 、 Dog ,而不包含 Zoo )。这里当然可以使用 call (* Animal.speak()) 来代替 target 。和静态的类型声明不同, target 并不能静态地确定的每一个连接点,因为匹配是基于运行时的类型信息。在使用 AJDT 的情况下,可以看到 target 和静态的类型声明的不同:

       1)使用 静态的类型声明的图示:

Screenshot3.png

Screenshot4.png


       可以看到,在方面AspectDemo中,before通知的左面有一个向上的小箭头表示其为通知,而Zoo中的void speak()方法中a.speak();一行的左面有个向右的小箭头,表明其匹配了一个通知(也就是 AspectDemo中的before通知)。
       2)
使用 target的图示:

Screenshot1.png

Screenshot2.png

       和 静态的类型声明不同,使用了 target的before前的箭头上有个问号,以表明 target动态的不确定性 。而Zoo的main中调用的方法z.speak()前有个类似于speak()中的 a.speak();的箭头,不同的是, z.speak()前的箭头上有个问号,这表明此处speak()并不确定是否匹配通知(因为target是动态确定连接点)。而实际上情况是, z.speak()确实不是通知的连接点。

        对于targetIdentifier)的使用,示例如下:

    publicpointcut speakCallTwo(Object o):

        call(* Animal.speak()) && target(o);

        before(Object o):speakCallTwo(o){

                System.out.println(o.getClass());

        }

    }

        通过将 target付给 Object o,可以在before通知中调用 o的一些操作。

        thistarget指示符的一个补充,它的格式与target相同。在含义上,this表示切入点所匹配的方法的调用类,而target表示匹配方法的目标类。例如:

        publicpointcut anotherSpeakCall():

            call(* speak()) && target(Animal) && this(Zoo);

        target(Animal) 表示void speak()方法是Animal及子类的,它不会匹配 Zoovoid speak()方法。而this(Zoo)会匹配调用了Animal及子类的void speak()方法的 Zoo类的方法,这里就是Zoovoid speak()方法。

        如上便是关于targetthis的基本用法。该文参考了《Eclipse AspectJ》和《AspectJ cookbook》。



你可能感兴趣的:(AspectJ学习(2)使用切入点 target和this)