Recipe 10.1. Capturing All Join Points Within a Program's Control Flow Initiated by an Initial Join PointProblemYou want to capture all join points encountered within the program control flow after and including an initiating join point selected by a separate pointcut. SolutionUse the cflow(Pointcut) pointcut. The syntax of the cflow(Pointcut) pointcut is: pointcut <pointcut name>(<any values to be picked up>) : cflow(<pointcut>) DiscussionThe cflow(Pointcut) pointcut has three key characteristics:
Example 10-1 shows how the cflow(Pointcut) is used to capture all join points in the program control flow after and including an initial join point as captured by the callInitialPointcut( ) pointcut. Example 10-1. Using the cflow(Pointcut) pointcut to capture all join points after and including a specific pointcutpublic aspect CFlowRecipe { /* Specifies calling advice whenever a method matching the following rules gets called: Class Name: MyClass Method Name: foo Method Return Type: void Method Parameters: an int followed by a String */ pointcut callInitialPointcut( ) : call( void MyClass.foo(int, String)); /* Specifies calling advice whenever a join point is encountered including and after the initial join point that triggers the pointcut that is specified in the parameter: Pointcut Name: callInitialPointcut */ pointcut cflowPointcut( ) : cflow(callInitialPointcut( )); // Advice declaration before( ) : cflowPointcut( ) && !within(CFlowRecipe +) { System.out.println( "------------------- Aspect Advice Logic --------------------"); System.out.println( "In the advice attached to the cflowPointcut point cut"); System.out.println( "Join Point Kind: " + thisJoinPoint.getStaticPart( ).getKind( )); System.out.println( "Signature: " + thisJoinPoint.getStaticPart( ).getSignature( )); System.out.println( "Source Line: " + thisJoinPoint.getStaticPart( ).getSourceLocation( )); System.out.println( "------------------------------------------------------------"); } } Figure 10-1 gives a more practical example of how the cflow(Pointcut) pointcut can be applied. Figure 10-1. How the cflow(Pointcut) pointcut can be appliedIt is worth going into a little more detail about what the cflow(Pointcut) does. This particular pointcut introduces the concept of a join point context. This is to say that every join point has a scope within which it is considered to be part of the control flow of the executing program. It is within this control flow that any encountered join point will trigger the cflow(Pointcut) pointcut and invoke any associated advice. The cflow(Pointcut) pointcut comes into effect and triggers its associated advice when the specified pointcut parameter is triggered by an initial join point. The advice associated with the cflow(Pointcut) will then be invoked for every join point encountered in the control flow within the context of the initial join point. Finally, the set of join points caught include the initial join point itself, which is the major difference between this pointcut and the cflowbelow(Pointcut). In the current implementation of the cflow(Pointcut) is implemented in such a way as to incur significant overhead when it is used. Where possible, and when pointcut reuse is not impacted, consider using the withincode(Signature) pointcut in preference over the cflow(Pointcut). See AlsoThe paper "Measuring the Dynamic Behaviour of AspectJ Programs" by Ganesh Sittampalam et al, available at http://www.sable.mcgill.ca/publications/papers/#oopsla2004, discusses some of the problems with performance that an AspectJ implementation may have over a handcoded solution; the withincode(Signature) pointcut is described in Recipe 9.3; the cflowbelow(Pointcut) pointcut is examined in Recipe 10.2; more information on a join point's context and environment is available in Chapter 13; the recipes in Chapter 12 describe techniques for combining pointcut definitions. |