当前位置: 首页 > 知识库问答 >
问题:

AspectJ-为什么当cflow未与

宋子辰
2023-03-14

我对AspectJ中的cflow或cflow有一个问题。

Cflow(切点)

在由切入点选择的连接点的控制流中选择所有连接点,包括切入点的连接点本身。

cflowbelow(切入点)

在切入点选择的连接点下方选择控制流中的所有连接点。

对于两者,我只能找到定义,并且:

当使用cflow或cflowbelow定义切入点时,我们需要确保切入点不会捕获来自同一方面的调用,否则它将调用递归方法调用,我们将得到StackOverflower错误。

这是因为cflow()还将捕获来自方面本身的方法调用,并尝试对其应用建议。这可以通过使用within()构造来避免。within()将类型(类或接口)名称作为参数,并捕获在该类型中定义的所有连接点。

但是没有解释当它们在没有内部或与

pointcut aPointcut(): execution(void Test.foo()) && !cflowbelow(execution(void Test.foo()));

这将与第一次执行测试相匹配。foo()仅在测试内部忽略任何气泡。foo()Test的另一个调用。foo(),或者调用扩展测试的类的方法。

我的问题是:当使用cflow时,例如在没有内部时,为什么它实际上会导致无限递归?如何使用cflow进行交织,从而导致这种递归?

共有1个答案

许远航
2023-03-14

一个简单的例子:

驱动程序应用程序:

package de.scrum_master.app;

public class Application {
    public static void sayHelloTo(String name) {
        System.out.println("Hello " + name + "!");
    }

    public static void main(String[] args) {
        sayHelloTo("world");
    }
}

方面:

package de.scrum_master.aspect;

import de.scrum_master.app.Application;

public aspect CflowRecursionDemo {
    // Attention, StackOverflowError!
    /*
    before() : cflow(execution(* Application.sayHelloTo(..))) {
        System.out.println(thisJoinPoint);
    }
    */

    before() : !within(CflowRecursionDemo) && cflow(execution(* Application.sayHelloTo(..))) {
        System.out.println(thisJoinPoint);
    }
}

注释掉的建议会导致堆栈溢出错误,而活动的建议不会。

控制台输出:

execution(void de.scrum_master.app.Application.sayHelloTo(String))
get(PrintStream java.lang.System.out)
call(java.lang.StringBuilder(String))
call(StringBuilder java.lang.StringBuilder.append(String))
call(StringBuilder java.lang.StringBuilder.append(String))
call(String java.lang.StringBuilder.toString())
call(void java.io.PrintStream.println(String))
Hello world!

说明:如您所见,活动建议的控制流中有许多连接点。这些连接点中的每一个都会再次触发活动建议,因为它们中的每一个都再次匹配切入点cflow(执行(*Application.sayHelloTo(...)))。建议和其他方法一样,只是碰巧在一个方面的内部。无论如何,它在自己切入点的控制流中再次触发建议,这再次在自己切入点的控制流中等等。无限递归!

 类似资料:
  • 问题内容: 首先让我注意,我使用AspectJ并且很喜欢它,但是我还能用它做什么呢。 我知道AspectJ可以用于日志记录。在某些情况下,它用于事务控制-大多与注释结合使用。像Spring Roo一样,AspectJ也可以用于通过(代码生成的)方法增强类。 但是我相信AspectJ和AOP通常可以用于以下方面:日志记录,事务控制和模拟子类。 那么,AspectJ和AOP还有哪些有用的用例呢? 问题

  • 我正在尝试设置Spring AoP框架,但我不想依赖AspectJ,因此我将在一个bean xml配置文件中声明我的方面、建议等,类似于以下内容: 每当我指定如上所述的切入点时,我都会收到以下错误: 当我把aspectjweaver.jar.包括在内时,我可以做到这一点,但这不应该是这样。有什么想法吗? 提前谢谢

  • 我的建议是正确执行并预先准备正确的操作,除了执行两次。我希望它只执行一次。应该触发通知的方法只执行一次,因为startTestSuite标题只在日志中打印一次。bean和上下文是在TestNG类中生成的。我尝试在initSpring()方法上使用@beforeClass和@beforeSuite标记运行它,结果相同。 进一步的上下文:这样做的目的是获取测试套件何时开始和结束的时间戳,以及各个测试何

  • 问题内容: 我正在使用Vue.js创建一个组件。 当我引用中的任何所述的生命周期钩(,,等等)它的计算结果为: 我的计算属性内部也发生了同样的事情: 我收到以下错误: 未捕获的TypeError:无法读取未定义的属性“ bar” 为什么要在这些情况下进行评估? 问题答案: 这两个示例都使用arrow函数,该函数绑定到与Vue实例不同的上下文。 根据文档: 不要在实例属性或回调(例如)上使用箭头功能

  • 问题内容: 我正在我的应用程序上执行以下操作,但是我无法获取routeChangeSuccess事件。 如下所示的非常简单的html也会失败 但是,当我单击链接时,我看到视图正在更新,但是从未触发$ routeChangeSucces事件。 有什么我想念的吗? *我遇到的 *另一个问题 是,可以挂接一个事件以知道视图已准备好,这样我就可以开始一些其他处理,例如document.ready()。 p

  • Spring AspectJ loadtime编织配置在构建和加载服务器时没有出现任何错误,但方面没有被调用。 下面是配置1)JDK 8服务器Jetty的列表 aop.xml 我还尝试使用aop.xml中的选项 我的maven中有以下依赖项 SampleAspect未被调用。我有几个方法(public,private和protected)用@ExecuteByContext注释。