【问题标题】:Reading and understanding AspectJ pointcuts?阅读和理解 AspectJ 切入点?
【发布时间】:2015-03-12 21:35:54
【问题描述】:
/* 0 */ pointcut services(Server s): target(s) && call(public * *(..))

这个切入点,命名为服务,在执行中挑选出那些点 当服务器对象调用它们的公共方法时,程序的。 它还允许使用服务切入点的任何人访问服务器 正在调用其方法的对象。 (取自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))?

还是我把这弄得太复杂了?我是否遗漏了一些重要的信息来帮助我理解这一点?

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

【问题讨论】:

  • 我认为answer 可能是:从左到右读取,从右到左执行...

标签: java aspectj pointcut pointcuts


【解决方案1】:

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中说明了不同的情况:在分支之间切换来尝试它们。在 aspect7 分支中有一个额外的案例,基于 6,我在 Server 中覆盖了 hashCode()

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


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

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

【讨论】:

    猜你喜欢
    • 2023-04-03
    • 1970-01-01
    • 2019-01-05
    • 2015-10-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多