/* 0 */ pointcut services(Server s): target(s) && call(public * *(..))

这个名为服务的切入点在执行过程中挑选出这些切入点
Server对象调用其公共方法时的程序代码。
它还允许使用服务切入点的任何人访问服务器
调用其方法的对象。
(取自https://eclipse.org/aspectj/doc/released/progguide/language-anatomy.html)

我正在尝试了解AspectJ的切入点,并且目前有点困惑。我的主要问题是:您如何阅读上述切入点,以及如何一起“迷惑”其含义?

为了说明我的困惑,让我们尝试从头开始构建:

以下切入点将拦截对任何对象的所有公共方法调用,对吗?
/* 1 */ pointcut services() : call(public * *(..))

现在,该怎么办:
/* 2 */ pointcut services() : call(public * Server.*(..))

我假设在调用Server对象的公共方法时,它将拦截任何点。

现在,我如何从这里转到初始示例0?我该如何阅读?

建立切入点时,您首先要提供参数列表吗?
/* 3a */ pointcut services(Server s) : call(public * *(..))

与上面的数字2相同吗? (我感觉它是行不通的,如果可行,它将“拦截”每个公共方法调用,就像数字1一样。)无论如何,以下内容是否相同? (我还没有通过本机切入点“捕获” s,所以我不能真正定义它,可以吗?)
/* 4a */ pointcut services(Server /* only type, no variable */) : call(public * *(..))

还是从指定本机切入点开始,以“捕获”目标对象,如下所示:
/* 3b */ pointcut services() : target(s) && call(public * *(..))

我想那仍然会拦截任何对象上的所有公共方法调用?

下面的工作是否仅拦截Server对象上的调用,并“捕获”该对象(而不使其可以稍后传递给例如建议)?
/* 5 */ pointcut services(/*nothing here*/) : target(s) && call(public * Server.*(..))

现在,回到原始切入点:
/* 0 */ pointcut services(Server s): target(s) && call(public * *(..))

是一样的吗
/* 6 */ pointcut services(Server s): target(s) && call(public * Server.*(..))

因此,总结一下:
您如何开始解密0?

您是先查看target切入点,然后查看services切入点的参数类型,然后“由内而外” /“从右向左”读取它吗?
还是先查看参数列表,然后查看services切入点以查看参数的来源(即target(s))?

还是我把这个变得太复杂了?我在某个地方缺少重要的地方来帮助我理解这一点吗?

编辑:手册从左到右解释-但是如果我还没有“执行” Server s,参数target(s)的参数从何而来?

最佳答案

1:是的,它拦截任何公共方法调用。

2:它拦截声明为作为Server的对象上的任何公共方法调用,而0拦截作为Server实例的对象上的任何公共调用。参见the semantics

3a:由于s未绑定,因此无法编译:

[ERROR] formal unbound in pointcut
        .../src/main/aspect/MyAspect.aj:18
pointcut services(Server s): call(public * *(..));

4a:语法无效,就像在接口中声明方法时需要命名参数一样:
[ERROR] Syntax error, insert "... VariableDeclaratorId" to complete FormalParameterList
        .../src/main/aspect/MyAspect.aj:18
pointcut services(Server): call(public * *(..));
                  ^

3b:也是无效的,尚未声明s:
[WARNING] no match for this type name: s [Xlint:invalidAbsoluteTypeName]
        .../src/main/aspect/MyAspect.aj:18
pointcut services(): target(s) && call(public * *(..));

5:和3b一样,s尚未声明。

6:与0不同,它仅将公共 Server 方法调用(即Server中声明的)与Server实例匹配。

我已经在a Github repository中说明了不同的情况:在分支之间切换以尝试它们。 Aspect6分支中有一个特殊情况,基于6,我在hashCode()中覆盖了Server

您可以(并且应该)尝试一下,以获得更好的理解。

为了回答您的最后一个问题,切入点的参数来自以下事实:我们希望(能够)通过将通知作为建议的参数提供来访问建议中的调用目标。建议的签名需要包含所有参考切入点的参数,并且切入点参数需要参考建议中的参数。

因此,要在通知中包含Server参数,我在切入点中需要它,并且需要将其绑定到切入点定义中的某些内容。

关于java - 阅读和理解AspectJ切入点?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/28969333/

10-09 03:32