AOP-错误:org.aspectj.runtime.internal.AroundClosure上的java.lang.*Error

我正在尝试使用面向方面的编程来执行一个简单的斐波那契函数并跟踪所有对任何调用
方法与Java中的方法不同,并显示嵌套
他们的水平.

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(int n,int r) {
        System.out.println("fib("+n+")="+r);
    }

    public static void main(String[] a) {
        report(4,fib(4));
    }
}

AspectJ代码:

package tracing;

public aspect Trace {
    String prefix = "";

    Object around(): call(* *(..)) && !within(java..*) && !within(FigureEditor..*) {
        System.out.println(prefix+thisJoinPoint.getSignature());
        prefix = ">" + prefix;
        Object result = proceed();
        prefix = prefix.substring(1);
        return result;
    }
}

注意:&& !within(FigureEditor .. *)仅用于避免使用其他程序包的类中的函数.

控制台输出-错误:

Exception in thread "main" java.lang.*Error     at
org.aspectj.runtime.internal.AroundClosure.<init>(AroundClosure.java:34)
    at tracing.Trace$AjcClosure1.<init>(Trace.aj:1)     at
tracing.Trace.ajc$around$tracing_Trace$1$ef88057b(Trace.aj:7)   at
tracing.Trace.ajc$around$tracing_Trace$1$ef88057b(Trace.aj:7)   at
tracing.Trace.ajc$around$tracing_Trace$1$ef88057b(Trace.aj:7)   at
tracing.Trace.ajc$around$tracing_Trace$1$ef88057b(Trace.aj:7)   at
tracing.Trace.ajc$around$tracing_Trace$1$ef88057b(Trace.aj:7)   at
tracing.Trace.ajc$around$tracing_Trace$1$ef88057b(Trace.aj:7)

更新:我想要的输出类似于以下内容:

void Test.main(String [])
>void Test.report(int, int)<br>
>>int Test.fib(int)<br>
>>>int Test.fib(int)<br>
>>>>int Test.fib(int)<br>
>>>>>int Test.fib(int)<br>
>>>>>int Test.fib(int)<br>
>>>>int Test.fib(int)<br>
>>>int Test.fib(int)<br>
>>>>int Test.fib(int)<br>
>>>>int Test.fib(int)<br>
>> void Test.write(String) fib(4)=3

解决方法:

我不确定您是使用Eclipse还是其他IDE来开发AspectJ代码,但是如果这样做,您可能会注意到在around()建议本身的方法主体中,IDE显示了AspectJ标记,这意味着它们本身(您的around()建议中的方法调用)将根据您的方面进行编织,如下图所示:

AOP-错误:org.aspectj.runtime.internal.AroundClosure上的java.lang.*Error

这意味着,为了避免在您的around()通知中发生无限递归(在该通知中,建议从自身内部被反复调用),您需要从获得建议中排除建议的控制流.您可以通过包含以下切入点表达式来轻松排除任何建议的控制流内的所有代码:!cflow(adviceexecution()),因此您的方面代码应如下所示(重新格式化):

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;
    }
}

AspectJ documentation on pointcut expressions

cflow(Pointcut): Picks out each join point in the control flow of any join point P picked out by Pointcut, including P itself.

adviceexecution(): Picks out all advice execution join points.

编辑:添加方面代码以反映更新的问题

您对原始问题的更新明确了您的意图.我已经更新了方面代码以反映这些更改.结果方面将如下所示:

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;
    }
}

我将所有建议执行代码的控制流排除在了Trace方面之外,并进行了运行时测试以排除java包中所有对代码的调用.

上一篇:Spring AspectJ,方法执行前的切入点,其中注释了方法OR类


下一篇:Spring的AOP切面编程