我正在检测第三方应用程序-并定义了以下切入点
@Aspect
public class MyAspect {
@Pointcut("execution(some.app.Application.new(..))")
public void appCreation() {
}
@After("appCreation()")
public void afterCreation() {
MyUtil.doSomething();
}
}
现在,问题出在
MyUtil.doSomething()
最终调用some.app.Application
的构造函数这一事实上-这当然是我的方面随后“检测到”的原因,并且再次调用MyUtil.doSomething()
并调用....您明白了。我试图在切入点定义中放入
&& !within(MyAspect)
,但没有帮助。在MyUtil
调用堆栈更远的情况下,有什么方法可以抑制切入点的检测?如果相关:
MyUtil.doSomething()
不是直接调用应用程序构造函数,而是在几次中间调用之后 最佳答案
好的,首先让我们重现您的问题:
Java类:
package de.scrum_master.app;
public class Application {
public Application() {
System.out.println("Creating application");
}
public static void main(String[] args) {
new Application();
}
}
package de.scrum_master.app;
public class MyUtil {
public static void doSomething() {
System.out.println("Doing something");
new Application();
}
}
引起递归的问题方面:
package de.scrum_master.aspect;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import de.scrum_master.app.MyUtil;
@Aspect
public class MyAspect {
@Pointcut("execution(*..Application.new(..))")
public void appCreation() {}
@After("appCreation()")
public void afterCreation() {
MyUtil.doSomething();
}
}
控制台日志:
Creating application
Doing something
Creating application
Doing something
(...)
Exception in thread "main" java.lang.StackOverflowError
at sun.nio.cs.UTF_8$Encoder.encodeLoop(Unknown Source)
at java.nio.charset.CharsetEncoder.encode(Unknown Source)
at sun.nio.cs.StreamEncoder.implWrite(Unknown Source)
at sun.nio.cs.StreamEncoder.write(Unknown Source)
at java.io.OutputStreamWriter.write(Unknown Source)
at java.io.BufferedWriter.flushBuffer(Unknown Source)
at java.io.PrintStream.write(Unknown Source)
at java.io.PrintStream.print(Unknown Source)
at java.io.PrintStream.println(Unknown Source)
at de.scrum_master.app.MyUtil.doSomething(MyUtil.java:5)
at de.scrum_master.aspect.MyAspect.afterCreation(MyAspect.aj:16)
at de.scrum_master.app.Application.<init>(Application.java:6)
at de.scrum_master.app.MyUtil.doSomething(MyUtil.java:6)
(...)
现在我们如何避免这个问题?如果建议已经在执行,即在当前控制流或
cflow()
中,我们需要避免执行建议。对于建议执行,甚至还有一个特殊的切入点adviceexecution()
。改进的方面避免了无限递归:
package de.scrum_master.aspect;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import de.scrum_master.app.MyUtil;
@Aspect
public class MyAspect {
@Pointcut("adviceexecution() && within(MyAspect)")
public void myAdvice() {}
@Pointcut("execution(*..Application.new(..))")
public void appCreation() {}
@After("appCreation() && !cflow(myAdvice())")
public void afterCreation() {
MyUtil.doSomething();
}
}
更正后的控制台日志:
Creating application
Doing something
Creating application
最后一点:到目前为止,我还没有质疑您的应用程序逻辑。现在我是:如果已经创建了一个实用程序方法,那么从一个实用程序方法中创建另一个应用程序真的有意义吗?我想即使这对我来说是一个有趣的AOP练习,但真正的问题出在Java代码中,而不是AspectJ代码中。
关于java - 由于无限循环而导致AspectJ StackoverflowError,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/31988226/