执行与执行呼叫加入点

问题描述 投票:0回答:2

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

pointcut methodCalls() : call (!static * test..*(..));
before(): methodCalls() {
        counter.methodCallCounter();
}

而第二个方面则计算“执行”连接点上的方法:

pointcut methodCalls() : execution (!static * test..*(..));
before(): methodCalls() {
        counter.methodCallCounter();
}

methodCallCounter() 是 counter 类中的静态方法。

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

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

aop aspectj
2个回答
56
投票

实际上,如果您了解

call()
execution()
切入点之间的基本区别,解释就非常简单:前者拦截所有调用者(即方法调用的来源),后者拦截方法执行本身,无论它们在哪里从起源。简而言之:
call
影响调用者,
execution
影响被调用者。

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

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

一般来说,在所有情况下,原因都是总体使用的代码和编织代码的子集之间的差异。换句话说:您(或方面)控制之下和之外的代码之间的差异。


12
投票

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

© www.soinside.com 2019 - 2024. All rights reserved.