捕获方法上的连接点
0.捕获方法调用
在调用具有特定签名的方法时,你想捕获它,可以使用call(Signature)
切入点,它的语法是:
pointcut [切入点名字](参数列表): call(<可选的方法修饰符> [返回类型] [类名].[方法名]([参数类型]))
注意三点:
- 1.call(Signature)是在方法调用上触发通知,其环境是调用类。
- 2.Signature可以包含通配符,用于选择不同类和方法上的一系列连接点。
- 3.方法修饰符是可选的。要么省略表示任何修饰符都可以,要么写具体的一个修饰符比如
public
,不能使用通配符。
0.0 通配符的使用
下表列出了把方法Signature提供给切入点声明时,使用通配符选项的一些示例。
具有通配符的方法签名 | 描述 |
---|---|
void MyClass.method(int, float) |
无论修饰符是什么,都会捕获方法上的连接点。 |
* MyClass.method(int, float) |
无论修饰符和返回类型是什么,都会捕获方法上的连接点 |
* *.method(int, float) |
无论修饰符、返回类型和类是什么,都会捕获方法上的连接点 |
* *.me*(int, float) |
无论修饰符是什么、返回类型和类是什么,只要方法名是以me 开头,则都会捕获方法上的连接点 |
* *.*(int, float) |
无论修饰符、返回类型、类和方法名是什么,都会捕获方法上的连接点 |
* *.*(*, float) |
无论修饰符、返回类型、类和方法名是什么,并且方法包含两个参数,第一个参数可以是任意类型,第二个参数是浮点类型,都会捕获方法上的连接点 |
* *.*(*, ..) |
无论修饰符、返回类型、类和方法名是什么,并且参数包含一个单值、后接任意数量任意类型的参数,都会捕获方法上的连接点 |
* *.*(..) 或者* *(..) |
无论修饰符、返回类型、类、方法名以及方法的参数个数与类型是什么,都会捕获方法上的连接点 |
* mypackage..*.*(..) |
捕获mypackage包和子包内的任何方法上的连接点 |
* MyClass+.*(..) |
捕获MyClass和任何子类中的任何方法上的连接点 |
根据AspectJ官方网站介绍,星号*
和两个点..
的用法是这样的:
- 星号
*
代表任何数量的除了点号.
之外的任何字符。 - 两个点号
..
代表任何数量的任何字符,也包括任何数量的点号.
。 - 但是在方法参数中,两个点号
..
来表示任何数量的任何类型的参数,而星号*
用来表示一个单独的参数。
下述的写法是错误的:
- 假如你想捕获MyClass中的method(int, float)方法,无论其方法修饰符是什么、无论其方法返回类型是什么。你可能会按照如下写法:
* * MyClass.method(int, float)
这里第一个星号*
用以匹配方法修饰符,不管其是public
还是private
都可以;第二个星号*
用以匹配方法返回类型,不管是int
或者是float
或是其他的都行。这个写法看似没有问题,但是一运行程序就会报错,为什么呢?我们前面要注意的三点中说了,方法的修饰符要么省略表示任何修饰符都可以,要么写一个具体的,不能用通配符。也就是说正确的写法是* MyClass.method(int, float)
。
当然假如限定了方法修饰符是public
,也可以写一个具体的:public * MyClass.method(int, float)
,这样是没问题的。
- 与上面的错误原因一样,这样也是错误的:
* void MyClass.method(int, float)
0.1 一个示例
在Test1包下,我们做一个简单的测试。
业务类名字为Service
,里面有一个test
方法,如下:
package Test1;
public class Service {
public void test(int a, float b) {
System.out.println("a + b = " + (a + b));
}
}
测试类名字为Main
,并由主方法,如下:
package Test1;
public class Main {
public static void main(String[] args) {
Service service = new Service();
service.test(2, 3.5f);
}
}
另外,我们新建一个切面,名字为CallAspect
,定义一个切入点callPointCut
,并且为其织入前置通知:
package Test1;
public aspect CallAspect {