i want to log all method call i make in my code except the ones within the logger, using 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());
}
}
the first advice in the class works fine (it writes every method call to the console), the second advice causes an infinite loop when calling org.myDomain.utils.Utils.printToConsole() method, which is advised by the calling advice.
I have found it is a common problem as described in the link http://www.eclipse.org/aspectj/doc/released/faq.php#q:infiniterecursion but i could not understand how to write the pointcut so an infinite loop would not be created.
plaes help
There are several problems in your code:
!codeWithinAspect
needs parentheses: !codeWithinAspect()
adviceWithInfiniteLoop()
combines execution()
and call()
pointcuts in this way: execution(foo) && !call(bar)
. Because a call joinpoint can never be an execution joinpoint the second part of the condition is always true and has no effect. Thus, it does not avoid the infinite loop.Logger
but also those within the control flow (cflow()
) of that aspect's methods, i.e. stuff directly or indirectly called by them.The solution is as follows:
Utility class for log output:
package org.myDomain.app;
public class Utils {
public static void printToConsole(Object object) {
System.out.println(object);
}
}
Driver application:
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");
}
}
Logger aspect:
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);
}
}
Console output:
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!
Enjoy!
Update: If you want to exclude all advice execution control flows you can also use this pointcut:
@Pointcut("cflow(adviceexecution())")
public void codeWithinAspect() {}