本节开始,我们将详细介绍pointcut的语法
一、call和execution
语法结构:execution([修饰符] 返回值类型 方法名(参数) [异常模式]) 蓝色表示可选部分。
例子:
- execution(public *.*(..)) 所有的public方法。
- execution(* hello(..)) 所有的hello()方法
- execution(String hello(..)) 所有返回值为String的hello方法。
- execution(* hello(String)) 所有参数为String类型的hello()
- execution(* hello(String..)) 至少有一个参数,且第一个参数类型为String的hello方法
- execution(* com.aspect..*(..)) 所有com.aspect包,以及子孙包下的所有方法
- execution(* com..*.*Dao.find*(..)) com包下的所有一Dao结尾的类的一find开头的方法
上面的几个例子,包括了修饰符,返回值,方法名,以及参数。大家可以根据需要灵活运用。接下来讲讲call 和 execution的区别,从字面理解:call为调用,而execution为执行。 事实上他们的区别也确实如此。
?
call捕获的joinpoint是签名方法的调用点,而execution捕获的则是执行点。为了有说服力,我写了一个demo.代码如下:
?
?
?
我们拦截了参数为:int的main方法。 这里用到了一内置的对象:thisJoinPoint,他表示当前jionPoint. 跟我们在java中的this 其实是差不多的,如果你不明白,那么你多运行一下,好好体会一下。getSourceLocation()表示元代吗的位置: 我们运行一下HelloWorld.java。 结果如下:
?
?
?
14是行号,即:main(5);
?
接下来,我们把HelloAspect中的call改为execution。发现打印结果如下:
?
?
在比照一下代码,看下输出。 现在明白了吧?? 一个是调用的地方,一个是执行的地方。
?
thisJoinPoint.getSourceLocation() 这段代码将会在我们以后的Demo中经常用到。这是一个跟踪调试的好办法。
?
二、within 和 withincode
?
现在假设你还有另外一个class,他也包含main()方法。
?
?
我们的HelloAspect如下:
?
?
这样,便会把HelloAspectDemo的main方法捕获到, 现在leader说: HelloAspectDemo不需要捕获。那我们怎么办勒?你首先想到的肯定是修改pointcut,指定到我们的HelloWorld类。 这当然是可以的,假设:现在还有5个类,也有main方法,也需要拦截。那你这解决办法肯定就不行了。(当然你也可以用 || 来组合他们)。这个时候就用到了我们的within了。 修改一下HelloAspect
?
?
?
再运行一下HelloAspectDemo,你会发现他被排除了,也就是说他没有被拦截到。
withincode与within相似,不过withcode()接受的signature是方法,而不是类。用法,意思都差不多,只不过是使用场合不同。
?
?
在接下来的一章,我将给大家介绍aspectj中最难理解的一个概念:控制流(cfow() cfowbelow())。