AOP-错误:org.aspectj.runtime.internal.AroundClosure上的java.lang.StackOverflower错误
我试图使用面向方面的编程来执行一个简单的斐波那契函数,并跟踪对任何 方法,并显示嵌套 他们的水平 Java代码:AOP-错误:org.aspectj.runtime.internal.AroundClosure上的java.lang.StackOverflower错误,java,stack-overflow,aop,aspectj,aspect,Java,Stack Overflow,Aop,Aspectj,Aspect,我试图使用面向方面的编程来执行一个简单的斐波那契函数,并跟踪对任何 方法,并显示嵌套 他们的水平 Java代码: package tracing; public class Test { static int fib(int n) { if (n<=1) return n; else return fib(n-1) + fib(n-2); } static void report(
package tracing;
public class Test {
static int fib(int n) {
if (n<=1)
return n;
else
return fib(n-1) + fib(n-2);
}
static void report(int n,int r) {
System.out.println("fib("+n+")="+r);
}
public static void main(String[] a) {
report(4,fib(4));
}
}
注意:&&!在(FigureEditor..*)
中仅用于避免不同包的类中的函数
控制台输出-错误: 线程“main”java.lang.StackOverflower中的异常位于 org.aspectj.runtime.internal.AroundClosure.(AroundClosure.java:34) 在tracing.Trace$AjcClosure1.(Trace.aj:1)在 tracing.Trace.ajc$大约$tracing\u Trace$1$ef88057b(Trace.aj:7)在 tracing.Trace.ajc$大约$tracing\u Trace$1$ef88057b(Trace.aj:7)在 tracing.Trace.ajc$大约$tracing\u Trace$1$ef88057b(Trace.aj:7)在 tracing.Trace.ajc$大约$tracing\u Trace$1$ef88057b(Trace.aj:7)在 tracing.Trace.ajc$大约$tracing\u Trace$1$ef88057b(Trace.aj:7)在 tracing.Trace.ajc$大约$tracing\u Trace$1$ef88057b(Trace.aj:7)
更新:我想要的输出类似于以下内容:
void Test.main(字符串[])
>无效测试报告(int,int)
>>int测试。fib(int)
>>>int测试。fib(int)
>>>>int测试。fib(int)
>>>>>int测试。fib(int)
>>>>>int测试。fib(int)
>>>>int测试。fib(int)
>>>int测试。fib(int)
>>>>int测试。fib(int)
>>>>int测试。fib(int)
>>无效测试。写入(字符串)fib(4)=3
我不确定您是否正在使用Eclipse或其他IDE来开发AspectJ代码,但如果使用了,您可能会注意到IDE在around()
通知本身的方法体中显示了AspectJ标记,这意味着它们本身(该方法在around()
通知内部调用)根据您的方面进行编织,如下图所示:
这意味着,为了避免在around()
通知中出现无限递归,即从通知本身内部重复调用通知,您需要将通知的控制流排除在通知之外。通过包含以下切入点表达式,可以轻松排除任何通知的控制流中的所有代码:!cflow(adviceexecution())
因此您的方面代码如下所示(稍微重新格式化):
从:
cflow(Pointcut)
:在由Pointcut选择的任何连接点p的控制流中选择每个连接点,包括p本身
adviceexecution()
:选择所有通知执行连接点
编辑:添加方面代码以反映更新的问题
您对原始问题的更新澄清了您对方面的意图。我已经更新了方面代码以反映这些更改。由此产生的方面如下所示:
public aspect Trace {
String prefix = "";
Object around(): call(* *(..))
&& !within(java..*)
&& !if(thisJoinPoint.getTarget()!=null && thisJoinPoint.getTarget().getClass().getName().startsWith("java"))
&& !within(FigureEditor..*)
&& !within(Trace) {
System.out.println(prefix+thisJoinPoint.getSignature());
prefix = ">" + prefix;
Object result = proceed();
prefix = prefix.substring(1);
return result;
}
}
我将排除所有通知执行代码的控制流替换为仅排除
跟踪
方面,并包括了一个运行时测试,以排除java
包中的所有代码调用。虽然Nándor的答案是正确的,但由于控制流切入点(如cflow())也很昂贵
和cflowDown()
在运行时进行计算。我建议您只需使用!在(Trace)
中,可以在编译时对其进行评估,而且速度更快
您还希望使用一种更简单的方法来排除对Java类的调用,而不涉及任何反射:!调用(*java..*(..))
包跟踪;
公共方面跟踪{
字符串前缀=”;
对象周围():
!在(跟踪范围内)&&
呼叫(**(..)&&
!call(*java..*(..)&&
!在(图编辑器..*)内
{
System.out.println(前缀+thisJoinPoint.getSignature());
前缀=“>”+前缀;
对象结果=继续();
前缀=前缀。子字符串(1);
返回结果;
}
}
这将产生所需的输出:
int跟踪.Test.fib(int)
>int跟踪.Test.fib(int)
>>int跟踪.Test.fib(int)
>>>int跟踪.Test.fib(int)
>>>int跟踪.Test.fib(int)
>>int跟踪.Test.fib(int)
>int跟踪.Test.fib(int)
>>int跟踪.Test.fib(int)
>>int跟踪.Test.fib(int)
无效跟踪测试报告(int,int)
fib(4)=3
我已经更新了我的问题,看看我想要的输出是什么。。。。现在执行的很好,没有问题。。。但我得到的结果是:int tracing.Test.fib(int)void tracing.Test.report(int,int)fib(4)=3
我在我的答案中添加了细节,以反映你问题中的变化。@NándorElődFekete:你认为我的答案如何?我认为它比你的要简单得多,不涉及运行时检查或反射。@kriegaex你完全正确。我的解决方案是次优的。你的答案很完美。我已经解决了你的格式问题。代码格式的语法是缩进4个空格,您也应该在控制台日志中使用它,而不是引用语法“>”。这很好。。我会记住有关cflow()
和cflowdown()
的信息。
public aspect Trace {
String prefix = "";
Object around(): call(* *(..))
&& !within(java..*)
&& !within(FigureEditor..*)
&& !cflow(adviceexecution()) {
System.out.println(prefix+thisJoinPoint.getSignature());
prefix = ">" + prefix;
Object result = proceed();
prefix = prefix.substring(1);
return result;
}
}
public aspect Trace {
String prefix = "";
Object around(): call(* *(..))
&& !within(java..*)
&& !if(thisJoinPoint.getTarget()!=null && thisJoinPoint.getTarget().getClass().getName().startsWith("java"))
&& !within(FigureEditor..*)
&& !within(Trace) {
System.out.println(prefix+thisJoinPoint.getSignature());
prefix = ">" + prefix;
Object result = proceed();
prefix = prefix.substring(1);
return result;
}
}