@CFlowStackDef (cflows={@CFlowDef(expr = "void POJO->method1()", called=true), @CFlowDef(expr = "void POJO->method2()", called=true), @CFlowDef(expr = "void POJO->method3()", called=true)}) public static CFlowStack cf123Before;
The first one declares that method1, method2, and method3 should be in the call stack in that order. The next
@CFlowStackDef (cflows={@CFlowDef(expr = "POJO->new()", called=true), @CFlowDef(expr = "void POJO->method3()", called=true)}) public static CFlowStack cf1ConAnd3;Says that the POJO constructor with an int parameter and method3 must be in the call stack in that order. As for Annotated composition and Annotated typedefs the fully qualified name of the @CFlowStackDef annotated field is used when we reference the CFlowStackDef by name. Again, the type CFlowStack is used as the type of the field for clarity, even though the actual type of the field is irrelevant.
@Bind (pointcut="execution(void POJO->method4())", cflow="(MyAspect.cf123Before OR MyAspect.cf123Before)") public Object methodAdvice(MethodInvocation invocation) throws Throwable { ... }This says to trigger the SimpleInterceptor on the execution of method4, but only when it is called within the context of method1, method2, and method3 OR contructor and method3.
The next example in MyAspect is for recursive methods. The example CFlowStackDef says that two calls to the recursive method must be in the call stack, but no more
@CFlowStackDef (cflows={@CFlowDef(expr = "void POJO->recursive(int)", called=true), @CFlowDef(expr = "void POJO->recursive(int)", called=true), @CFlowDef(expr = "void POJO->recursive(int)", called=false)}) public static CFlowStack cf2Recursions; @Bind (pointcut="execution(void POJO->recursive(int))", cflow="MyAspect.cf2Recursions") public Object recursiveAdvice(MethodInvocation invocation) throws Throwable { ... }
Combined with the execution binding, the SimpleInterceptor will only be triggered on the second call to the recursive method.
$ antIt will javac the files and then run the AOPC precompiler to manipulate the bytecode, then finally run the example. The output should read as follows:
run: [java] --- pojo.method4(); --- [java] method4 [java] --- pojo.method3(); --- [java] method3 [java] method4 [java] --- pojo.method2(); --- [java] method2 [java] method3 [java] method4 [java] --- pojo.method1(); --- [java] method1 [java] method2 [java] method3 [java] <<< MyAdvice.methodAdvice accessing: public void POJO.method4() [java] method4 [java] >>> Leaving MyAdvice.methodAdvice [java] --- pojo.recursive(); --- [java] recursive: 1 [java] recursive: 2 [java] recursive: 3 [java] --- new POJO(int); --- [java] method3 [java] method4