执行比 呼叫加入点

use*_*337 21 aspectj

我有两个不同的方面类来计算执行测试程序的非静态方法调用的数量.第一个方面计算"呼叫"连接点的方法:

pointcut methodCalls() : call (!static * test..*(..));
before(): methodCalls() {
        counter.methodCallCounter();
}
Run Code Online (Sandbox Code Playgroud)

而第二个方面计算"执行"连接点的方法:

pointcut methodCalls() : execution (!static * test..*(..));
before(): methodCalls() {
        counter.methodCallCounter();
}
Run Code Online (Sandbox Code Playgroud)

methodCallCounter()是计数器类中的静态方法.

小测试程序的方法调用次数是相同的.但是当我用更大的程序更改测试程序时,第二个方面类(带执行切入点)中的方法调用数量大于带有调用切入点的方面类中的方法调用数.这是合理的,因为调用连接点不会选择使用super进行的调用,因此不会对它们进行计数.

但是,我遇到了一种情况,对于程序的特定执行,具有"调用切入点"的方面类中的非静态方法调用的数量高于具有"执行切入点"的方面类中的方法调用的数量.我找不到任何解释为什么会发生这种情况.任何关于第二种情况的原因的想法都值得赞赏.

kri*_*aex 42

如果你理解call()execution()切入点之间的基本区别,那么解释很简单:前者拦截所有调用者(即方法调用的来源),后者无论它们来自何处都会拦截调用本身.

那么两个切入点触发的拦截次数怎么会有所不同呢?

  • 如果从您自己的代码中调用JRE/JDK方法,则AspectJ可以编入您的调用,但不能编入JDK中的执行连接点(除非您已创建编织JDK作为准备步骤).因此,呼叫次数将高于执行次数.
  • 类似地,如果您调用第三方库中没有与AspectJ编织的方法,因为它们在LTW或CTW期间不在路径中,则不会再捕获执行.
  • 最后,但并非最不重要的是,如果您自己的编织代码由第三方库或JRE/JDK类调用,则可能会发生相反的情况.在这种情况下,计算的执行次数将高于调用次数,因为它们来自AspectJ代码控制之外的位置.

通常,在所有情况下,原因是总体使用的代码与编织代码的子集之间的差异.换句话说:您(或方面')控件之下和之外的代码之间的差异.

  • [AspectJ手册](https://www.eclipse.org/aspectj/doc/next/progguide/language-joinPoints.html#call-vs-execution)解释了基本的区别。在[此答案](/sf/answers/1977691971/)中,我使用伪代码对其进行了详细说明,以更好地理解。基本的区别是`call()`将代码编织到调用方法的所有位置,即,如果从代码中的500个不同位置调用该方法,则会将建议代码编织到这500个位置。但是,将“ execute()”编织到方法本身中,即仅编织一次,通常效率更高。 (4认同)
  • 不,我们不可以.像cflow()`或`if()`这样的切入点是在运行时确定的. (3认同)
  • (续)选择哪个取决于您是否对调用的代码具有控制权,以及是否可以将方面编织进去。如果可以的话,通常会使用`execution()`,如果不能的话,通常会使用`call()`。在其他情况下,可能会选择`call()`,例如,如果您想绑定`this()`或使用`JoinPoint.getThis()`来执行调用对象(调用者)而不是被调用对象(被叫)但这太复杂了,无法用一两个简短的评论来解释。 (2认同)

fat*_*ari 12

这张图可以帮助您直观地了解执行和调用之间的区别: 调用与exe