Recipe 13.6. Executing Advice Only After a Normal Return from a Join PointProblemYou want advice to execute after a specific join point only if that join point returned normally. SolutionUse the after( ) returning or after() returning(<ReturnType> <Identifier>) types of advice. DiscussionExample 13-6 shows how to specify that the advice should only be executed after the call to void MyClass.foo(int) if the call to the method returns normally. Example 13-6. Executing advice after a method call if that call returns normallypublic aspect AfterReturningAdviceRecipe { /* 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 callPointCut( ) : call(void MyClass.foo(int)); // Advice declaration after( ) returning : callPointCut( ) && !within(AfterReturningAdviceRecipe +) { System.out.println( "------------------- Aspect Advice Logic --------------------"); System.out.println( "Source Location: " + thisJoinPoint.getStaticPart( ).getSourceLocation( )); System.out.println( "------------------------------------------------------------"); } } The after( ) returning advice in Example 13-6 does not access a returning value from the join point because the void MyClass.foo(int) method does not return any value. If the join point did return a value, then AspectJ provides the after( ) returning(ReturnType Identifier) variation that lets you assign the returning value to an identifier( ) and access the value in the corresponding advice block, as shown in Example 13-7. Example 13-7. Accessing a method's return value if the method returned normallypublic aspect AfterReturningValueAdviceRecipe { /* Specifies calling advice whenever a method matching the following rules gets called: Class Name: MyClass Method Name: foo Method Return Type: int Method Parameters: an int followed by a String */ pointcut callPointCut( ) : call(int MyClass.foo(int)); // Advice declaration after( ) returning(Object value) : callPointCut( ) && !within(AfterReturningAdviceRecipe +) { System.out.println( "------------------- Aspect Advice Logic --------------------"); System.out.println( "Source Location: " + thisJoinPoint.getStaticPart( ).getSourceLocation( )); System.out.println( "Value being returned: " + value); System.out.println( "------------------------------------------------------------"); } An interesting side effect of using the after( ) returning(<Type> <Identifier>) advice to access a primitive type, as shown in Example 13-7, is that the primitive int value must be boxed in an instance of the Integer class to be passed to the advice. When the return type expected by the advice is of type Object, and if the return value is a primitive type, AspectJ will automatically and transparently box the primitive value into its corresponding Java class. This automatic and transparent boxing behavior, where a value of type Object is expected and primitives are to be passed to or from the advice, is also used by the around( ) form of advice. The after( ) returning forms of advice provide a finer filter of the join points that trigger the advice than the normal after( ) type of advice (covered in Recipe Recipe 13.5). The code within the after( ) returning advice block will be executed if the encountered join point returns without raising an exception offering a mechanism by which to avoid capturing join points on methods that have experienced problems. See AlsoThe call(Signature) pointcut is described in Recipe 4.1; the within(TypePattern) pointcut is described in Recipe 9.1; the thisJoinPoint variable and the context it encapsulates is examined in Recipe 13.2; the around( ) advice is described in Recipe 13.4; the after( ) advice is shown in Recipe 13.5. |