3
/* 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)哪里?

4

1 回答 1

4

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

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

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方法调用(即在 中声明)。ServerServer

我在Github 存储库中说明了不同的案例:在分支之间切换以尝试它们。aspect7 分支中有一个额外的案例,基于 6,我在其中覆盖hashCode()Server.

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


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

所以,要Server在通知中有一个参数,我需要在切入点中使用它,并且它需要绑定到切入点定义中的某些内容。

于 2015-03-11T13:58:57.390 回答