Recipe13.4.Executing Advice Around a Join Point


Recipe 13.4. Executing Advice Around a Join Point

Problem

You want advice to execute around the join points that trigger it.

Solution

Use the around( ) type of advice.

Discussion

Example 13-4 shows how to execute advice around the void MyClass.foo(int, String) method.

Example 13-4. Executing advice around a method call
public aspect AroundAdviceRecipe  {    /*            Specifies calling advice whenever a method            matching the following rules gets called:                Class Name: MyClass            Method Name: bar            Method Return Type: int            Method Parameters:             */    pointcut callFooPointCut( ) : call(int MyClass.foo( ));    /*     Specifies calling advice whenever a method     matching the following rules gets called:         Class Name: MyClass     Method Name: bar2     Method Return Type: int     Method Parameters: int     */    pointcut callBarPointCut(int value) : call(int MyClass.bar(int))       && args(value);        /*           Specifies calling advice whenever a method           matching the following rules gets called:              Class Name: MyClass           Method Name: baz           Method Return Type: int           Method Parameters:            */    pointcut callBazPointCut( ) : call(int MyClass.baz( ));     // Advice declaration         // This advice will be executed before the pointcut that picks it    int around( ) : callFooPointCut( ) && !within(AroundAdviceRecipe +)    {       System.out.println(          "------------------- Aspect Advice Logic --------------------");       System.out.println(          "Signature: " + thisJoinPoint.getSignature( ));       System.out.println(          "Source Location: "             + thisJoinPoint.getStaticPart( ).getSourceLocation( ));       System.out.println(          "------------------------------------------------------------");       return proceed( );    }     // Advice declaration         // This advice will be executed before the pointcut that picks it    int around(int value) : callBarPointCut(value)       && !within(AroundAdviceRecipe +)    {       System.out.println(          "------------------- Aspect Advice Logic --------------------");       System.out.println(          "Signature: " + thisJoinPoint.getSignature( ));       System.out.println(          "Source Location: "             + thisJoinPoint.getStaticPart( ).getSourceLocation( ));       System.out.println(          "------------------------------------------------------------");       return proceed(value);    }        // Advice declaration    // This advice will be executed before the pointcut that picks it   int around( ) : callBazPointCut( ) && !within(AroundAdviceRecipe +)   {      System.out.println(         "------------------- Aspect Advice Logic --------------------");      System.out.println(         "Signature: " + thisJoinPoint.getSignature( ));      System.out.println(         "Source Location: "            + thisJoinPoint.getStaticPart( ).getSourceLocation( ));      System.out.println(         "------------------------------------------------------------");      return 200;   } }

The around( ) advice is a powerful construct that indicates to AspectJ the advice should be run instead of the join point that has triggered it. This allows overriding the original logic present in the application. This recipe shows the around( ) advice being applied passively and actively according to whether the proceed() call is made from within the around( ) advice block. according to whether the proceed( ) call is made from within the around( ) advice block. Figure 13-1 shows the behavior from Example 13-4 where passive and active around() advice are being applied.

Figure 13-1. Using around( ) advice passively and actively on a call(TypePattern) pointcut


The proceed( ) call indicates the around() advice should continue with executing the original join point logic, passing any values that were originally available. In the first piece of advice in Example 13-4, there were no parameters to pass; in the second, there was an int available on the call join point, and for this reason the parameter must be passed on to the proceed( ) call. The parameter could have a completely different value than the original but not a different type or class; otherwise, this will cause a compilation error.

Contrasting with the more passive form of the around() advice type shown in the first two pieces of advice in Example 13-4, around( ) advice can be used to override the join point that has triggered it. The MyClass.baz( ) method is overridden by the third around( ) advice because of the proceed( ) call. To complete the overriding of the original join point, the around( ) advice returns a value different from what was originally intended.

The same overriding approach can be used to override constructors. This mechanism is useful when the actual object being instantiated needs to be controlled by the aspect. The return object from a constructor is the newly instantiated object and as such can be decided by the advice. The advice could return a different class of object than the one expected by the target application as long as it is an appropriate class.

The around( ) advice must have a return value specified, but this can be void if no value is needed. A return value can be obtained from the original logic in terms of the return from the proceed( ) call or a totally new object of a class appropriate for the join points captured.

If the advice is applied to join points with different return types, then the advice may declare that its return value will be of the Object class. In the case where one of those return types is a primitive type, such as a float or an int, the AspectJ will automatically "unbox" the primitive return value at runtime.

For example, when an around( ) advice block that returns an Object advises a method call join point on a method that returns a float primitive type, the advice must "box" the return value as an instance of the Float class so it can be returned as an Object according to the advice declaration. Where the join point returns, the return value is automatically and transparently unboxed back to the primitive float according to the method's original signature.

Performance is a consideration when using around() advice. There is a performance penalty when using around( ) advice in AspectJ, which means that a combination of the before() and after( ) returning form of advice wherever possible.

See Also

The 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 hand-coded solution; The after( ) returning form of advice is discussed in Recipe 13.6; the call(Signature) pointcut is described in Recipe 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; discusses some common pointcut idioms, one of which being the ability to ignore exception handling and object initialization join points, as these do not support around( ) advice.



AspectJ Cookbook
Aspectj Cookbook
ISBN: 0596006543
EAN: 2147483647
Year: 2006
Pages: 203
Authors: Russ Miles

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net