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)使用 静态的类型声明的图示:2)使用 target的图示:
对于target(Identifier)的使用,示例如下:
publicpointcut speakCallTwo(Object o):
call(* Animal.speak()) && target(o);
before(Object o):speakCallTwo(o){
System.out.println(o.getClass());
}
}
通过将 target付给 Object o,可以在before通知中调用 o的一些操作。
this是target指示符的一个补充,它的格式与target相同。在含义上,this表示切入点所匹配的方法的调用类,而target表示匹配方法的目标类。例如:
publicpointcut anotherSpeakCall():
call(* speak()) && target(Animal) && this(Zoo);
target(Animal) 表示void speak()方法是Animal及子类的,它不会匹配 Zoo的void speak()方法。而this(Zoo)会匹配调用了Animal及子类的void speak()方法的 Zoo类的方法,这里就是Zoo的void speak()方法。
如上便是关于target和this的基本用法。该文参考了《Eclipse AspectJ》和《AspectJ cookbook》。