/* 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/