gpt4 book ai didi

java - Aspectj - 如何从同一建议中调用建议方法,而不触发无限循环

转载 作者:行者123 更新时间:2023-12-02 05:19:11 24 4
gpt4 key购买 nike

我想使用 AspectJ 记录我在代码中进行的所有方法调用(记录器中的方法调用除外)。

@Aspect
public class Logger
{
// Point Cuts
//-----------
@Pointcut("execution(* org.myDomain.*..*.*(..))")
public void selectAll(){}

@Pointcut("within(Logger) && call(* *(..))")
public void codeWithinAspect(){}

// Advices
//-----------
@Before("selectAll()")
public void adviceThatWorksFine(JoinPoint joinPoint)
{
System.out.print(joinPoint.getSignature().toString());
//Utils.printToConsole(joinPoint.getSignature().toString());
}

@Before("selectAll() && !codeWithinAspect")
public void adviceWithInfiniteLoop(JoinPoint joinPoint)
{
//System.out.print(joinPoint.getSignature().toString());
Utils.printToConsole(joinPoint.getSignature().toString());
}
}

类中的第一个建议工作正常(它将每个方法调用写入控制台),第二个建议在调用 org.myDomain.utils.Utils.printToConsole() 方法时导致无限循环,这是由调用建议的建议。

我发现这是一个常见问题,如链接中所述 http://www.eclipse.org/aspectj/doc/released/faq.php#q:infiniterecursion但我不明白如何编写切入点,这样就不会创建无限循环。

请帮忙

最佳答案

您的代码中存在几个问题:

  • !codeWithinAspect 需要括号:!codeWithinAspect()
  • adviceWithInfiniteLoop() 以这种方式组合 execution()call() 切入点:execution(foo) && !call (栏)。由于调用连接点永远不可能是执行连接点,因此条件的第二部分始终为 true 并且无效。因此,它并不能避免无限循环。
  • 您不仅要排除方面 Logger 内的连接点,还要排除该方面方法的控制流 (cflow()) 内的连接点,即直接或间接的内容由他们调用。

解决办法如下:

日志输出的实用类:

package org.myDomain.app;

public class Utils {
public static void printToConsole(Object object) {
System.out.println(object);
}
}

驱动程序应用程序:

package org.myDomain.app;

public class Application {
public static void sayHelloTo(String counterpart) {
Utils.printToConsole("Hello " + counterpart + "!");
}

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

记录器方面:

package org.myDomain.aspect;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.myDomain.app.Utils;

@Aspect
public class Logger {
@Pointcut("execution(* org.myDomain..*(..))")
public void selectAll() {}

@Pointcut("cflow(within(Logger))")
public void codeWithinAspect() {}

@Before("selectAll() && !codeWithinAspect()")
public void advice(JoinPoint joinPoint) {
Utils.printToConsole(joinPoint);
}
}

控制台输出:

execution(void org.myDomain.app.Application.main(String[]))
execution(void org.myDomain.app.Application.sayHelloTo(String))
execution(void org.myDomain.app.Utils.printToConsole(Object))
Hello world!

享受吧!

更新:如果您想排除所有建议执行控制流,您也可以使用此切入点:

@Pointcut("cflow(adviceexecution())")
public void codeWithinAspect() {}

关于java - Aspectj - 如何从同一建议中调用建议方法,而不触发无限循环,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26641283/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com