能否举例说明AspectJ中cFlow(P && Q)的作用是什么?

4
我正在阅读AspectJ文档,并且不太理解他们在切入点组合上的观点。特别是,当使用该切入点的建议会被执行时,我不明白cFlow(P && Q)的作用。
我找到了一份乌得勒支大学课程的演示文稿,解释道:
cflow是从参数切入点流出的连接点集合。这意味着cflow(P)和cflow(Q)是两个集合的交集,而cflow(P&& Q)意味着您首先组合切入点P和Q,然后所有从中流出的连接点都在此集合中。
他们列出了cFlow(P) && cFlow(Q) (pointcut flowPAndflowQ() : cflow(execution(* Example.P(..))) && cflow(execution(* Example.Q(..))) && within(Example);)的所有连接点,对我来说,这看起来像是单个语句的所有控制流点的交集-如果您愿意,就像他们所说的那样:P ∩ Q:

从P流动 - execution(void Example.P())
从P流动 - call(void Example.Q())
从P流动 - execution(void Example.Q())
从Q流动 - execution(void Example.Q())
从P和Q流动 - execution(void Example.Q())

(他们的示例类似于AspectJ文档中的示例,只是缺少println()语句。)

我仍然不理解的是cFlow(P && Q)会做什么。

这是否意味着“获取所有在P中的连接点,然后添加所有在Q中的连接点,然后匹配任何从它们中的任何一个流出的内容”?如果是这样,我不理解AspectJ示例中的println()语句:System.out.println("should not occur");。当然,如果我添加P和Q中的所有流点(即P + Q),那应该是P ∩ Q的超集(并集), P ∪ Q?或者这是否意味着“获取P中所有也在Q中的连接点”,即下面X()中的所有流点?
public void P() { X(); }
public void Q() { X(); }
public void X() { /* all that is in the body of X() */ }

或者像AspectJ的示例所示,它永远不会发生?(为什么?)
如果有人能够解释一下,我会非常感激。 :)
1个回答

1

这是什么意思,“获取所有在P中的连接点,然后添加所有在Q中的连接点,然后匹配从它们中的任何一个流出的任何内容”?

不,它的意思是获取所有在P和Q中的连接点,因此它是交集。

还是它的意思是“获取在P中也在Q中的所有连接点”,即下面X()中的所有流点?

是的,对于“获取在P中也在Q中的所有连接点”,但对于其余部分则不是。原因是切入点P定义了一个单一的连接点:execution(void Example.P()),而切入点Q定义了一个单一的连接点:execution(void Example.Q())。因为这些连接点是不同的,所以它们的交集是一个空集合。从空集合中取出cflow也是一个空集合。这就是为什么在AspectJ文档中标记了该切入点“不应发生”的原因。

希望这可以帮助你!

这是Power Point演示文稿中具有误导性的引用:

cflow(P && Q)的意思是首先结合点切P和Q,然后所有从它们中流出的连接点都在这个集合中。

将单词“combine”替换为“intersect”。

我在Github上创建了一个简单的示例,复制了PowerPoint演示文稿中的示例:https://github.com/medvedev1088/aspectj-cflow-composition-example

public class Example {
    public void P() {
        Q();
    }

    public void Q() {
    }

    public static void main(String[] args) {
        new Example().P();
    }
}

如果你运行它,输出应该像这样:
pointcut: P                    join point: execution(Example.P())
pointcut: flowP                join point: execution(Example.P())
pointcut: flowP                join point: call(Example.Q())
pointcut: Q                    join point: execution(Example.Q())
pointcut: flowP                join point: execution(Example.Q())
pointcut: flowQ                join point: execution(Example.Q())
pointcut: flowPAndflowQ        join point: execution(Example.Q())

这表明只有3个连接点:
A: execution(Example.P())
B: call(Example.Q())
C: execution(Example.Q())

切入点:

pointcut P includes only A
pointcut Q includes only C
pointcut flowP includes A, B and C
pointcut flowQ includes only C
pointcut flowPAndflowQ includes only C

我们现在可以看到,P && Q 是一个空集,而 flowP && flowQ 包含 C。
我还添加了额外的切入点:cflow(P() && publicMethods())(此切入点的建议在代码中被注释掉)。publicMethods() 是 execution(public * *(..))。与 cflow(P() && Q()) 不同,它不会导致空集。

我现在感到更加困惑了。所以,cflow(P) && cFlow(Q) 是交集(包括两个切入点下游的连接点),而 cFlow(P && Q) 也是一个交集,但与第一个不同?这是因为后者只看初始切入点,而不考虑“下游”的连接点吗?你能否构造一个示例来说明后者的工作原理呢? :) - Christian
1
这是因为后者只查看初始切入点,而不是“下游”的连接点吗?没错。也许你能构建一个示例来展示后者是如何工作的吗?我更新了我的回答。请在Github上检查示例项目https://github.com/medvedev1088/aspectj-cflow-composition-example。希望它能澄清事情。 - medvedev1088
感谢您的示例和努力让我看到光明。我不确定我完全理解了;我会明天再次查看,以清醒的头脑。我确实将我的问题发送到了 AspectJ 列表,但是在您更新回复之前不久。仅为了自己的方便,我将 cFlow(P && Q) 写成了 pointcut cFlowPandQ : cFlow(execution(* Example.P()) && execution(* Example.Q())) && within(Example); 那么,整个重点是您无法同时执行 P 和 Q 吗? (当 P 调用 Q 时,这不是发生的情况吗?) - Christian
1
所以,整个重点是你不能同时执行P和Q吗? 没错。在程序的任何给定执行点上,你只能处于一个连接点。所以当P调用Q时,连接点是call(Example.Q())。执行(Example.P())连接点发生在call(Example.Q())之前。执行(Example.Q())发生在call(Example.Q())之后。 - medvedev1088
所以,cflow(P() && publicMethods()) 之所以有效,是因为它本质上是相同连接点的不同名称(切入点)在同一时间?(pcut: P -> jn pts: execution(Example.P())pcut: execPublicMethods -> jn pts: execution(Example.P()), execution(Example.Q()),所以当 Example.P() 被执行时,两个切入点都会被触发 - 我不明白的是为什么我会得到以下结果:pcut: flowPAndPublic -> jn pts: execution(Example.P()), call(Example.Q()), execution(Example.P()),对于 cflow(P() && publicMethods()) && within(example.Example);我现在只期望第一个结果..) - Christian
1
你是对的。 P() && publicMethods() 相当于只有 P()。这是因为当你交叉两个连接点集时,你只得到执行(Example.P()),它等于 P()。这意味着 cflow(P() && publicMethods()) 等同于 cflow(P()),其中包括 3 个连接点。 :) - medvedev1088

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接