Wednesday, 15 July 2015

java - Aspectj - how to call advised method from within same advice, without triggering an infinite loop -



java - Aspectj - how to call advised method from within same advice, without triggering an infinite loop -

i want log method phone call create in code except ones within 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 class works fine (it writes every method phone call console), sec advice causes infinite loop when calling org.mydomain.utils.utils.printtoconsole() method, advised calling advice.

i have found mutual problem described in link http://www.eclipse.org/aspectj/doc/released/faq.php#q:infiniterecursion not understand how write pointcut infinite loop not created.

plaes help

there several problems in code:

!codewithinaspect needs parentheses: !codewithinaspect() advicewithinfiniteloop() combines execution() , call() pointcuts in way: execution(foo) && !call(bar). because phone call joinpoint can never execution joinpoint sec part of status true , has no effect. thus, not avoid infinite loop. you not want exclude joinpoints within aspect logger within command flow (cflow()) of aspect's methods, i.e. stuff straight or indirectly called them.

the solution follows:

utility class log output:

class="lang-java prettyprint-override">package org.mydomain.app; public class utils { public static void printtoconsole(object object) { system.out.println(object); } }

driver application:

class="lang-java prettyprint-override">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:

class="lang-java prettyprint-override">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:

class="lang-none prettyprint-override">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 want exclude advice execution command flows can utilize pointcut:

class="lang-java prettyprint-override">@pointcut("cflow(adviceexecution())") public void codewithinaspect() {}

java aspectj infinite-loop pointcut

No comments:

Post a Comment