| <html><head> |
| <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"> |
| <title>Advice</title><link rel="stylesheet" href="aspectj-docs.css" type="text/css"><meta name="generator" content="DocBook XSL Stylesheets V1.44"><link rel="home" href="index.html" title="The AspectJTM Programming Guide"><link rel="up" href="semantics.html" title="Appendix B. Language Semantics"><link rel="previous" href="semantics-pointcuts.html" title="Pointcuts"><link rel="next" href="semantics-declare.html" title="Static crosscutting"></head><body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="navheader"><table width="100%" summary="Navigation header"><tr><th colspan="3" align="center">Advice</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="semantics-pointcuts.html">Prev</a> </td><th width="60%" align="center">Appendix B. Language Semantics</th><td width="20%" align="right"> <a accesskey="n" href="semantics-declare.html">Next</a></td></tr></table><hr></div><div class="sect1"><a name="semantics-advice"></a><div class="titlepage"><div><h2 class="title" style="clear: both"><a name="semantics-advice"></a>Advice</h2></div></div><p> |
| Each piece of advice is of the form |
| |
| <blockquote class="blockquote"><tt>[ strictfp ] <i><tt>AdviceSpec</tt></i> [ |
| throws <i><tt>TypeList</tt></i> ] : |
| <i><tt>Pointcut</tt></i> { |
| <i><tt>Body</tt></i> } </tt></blockquote> |
| |
| where <i><tt>AdviceSpec</tt></i> is one of |
| </p><div class="itemizedlist"><ul><li><a name="d0e6012"></a><tt>before( <i><tt>Formals</tt></i> ) </tt></li><li><a name="d0e6018"></a><tt>after( <i><tt>Formals</tt></i> ) returning |
| [ ( <i><tt>Formal</tt></i> ) ] </tt></li><li><a name="d0e6027"></a><tt>after( <i><tt>Formals</tt></i> ) throwing [ |
| ( <i><tt>Formal</tt></i> ) ] </tt></li><li><a name="d0e6036"></a><tt>after( <i><tt>Formals</tt></i> ) </tt></li><li><a name="d0e6042"></a><tt><i><tt>Type</tt></i> |
| around( <i><tt>Formals</tt></i> )</tt></li></ul></div><p> |
| and where <i><tt>Formal</tt></i> refers to a |
| variable binding like those used for method parameters, |
| of the form |
| <tt><i><tt>Type</tt></i></tt> |
| <tt><i><tt>Variable-Name</tt></i></tt>, |
| and <i><tt>Formals</tt></i> refers to a comma-delimited |
| list of <i><tt>Formal</tt></i>. |
| </p><p> |
| Advice defines crosscutting behavior. It is defined in terms of |
| pointcuts. The code of a piece of advice runs at every join point |
| picked out by its pointcut. Exactly how the code runs depends on the |
| kind of advice. |
| </p><p> |
| AspectJ supports three kinds of advice. The kind of advice determines how |
| it interacts with the join points it is defined over. Thus AspectJ |
| divides advice into that which runs before its join points, that which |
| runs after its join points, and that which runs in place of (or "around") |
| its join points. |
| </p><p> |
| While before advice is relatively unproblematic, there can be three |
| interpretations of after advice: After the execution of a join point |
| completes normally, after it throws an exception, or after it does either |
| one. AspectJ allows after advice for any of these situations. |
| </p><pre class="programlisting"> |
| aspect A { |
| pointcut publicCall(): call(public Object *(..)); |
| after() returning (Object o): publicCall() { |
| System.out.println("Returned normally with " + o); |
| } |
| after() throwing (Exception e): publicCall() { |
| System.out.println("Threw an exception: " + e); |
| } |
| after(): publicCall(){ |
| System.out.println("Returned or threw an Exception"); |
| } |
| } |
| </pre><p> |
| After returning advice may not care about its returned object, in which |
| case it may be written |
| </p><pre class="programlisting"> |
| after() returning: call(public Object *(..)) { |
| System.out.println("Returned normally"); |
| } |
| </pre><p> |
| If after returning does expose its returned object, then the |
| type of the parameter is considered to be an |
| <tt>instanceof</tt>-like constraint on the advice: it |
| will run only when the return value is of the appropriate type. |
| </p><p> |
| A value is of the appropriate type if it would be assignable to |
| a variable of that type, in the Java sense. That is, a |
| <tt>byte</tt> value is assignable to a |
| <tt>short</tt> parameter but not vice-versa, an |
| <tt>int</tt> is assignable to a |
| <tt>float</tt> parameter, <tt>boolean</tt> |
| values are only assignable to <tt>boolean</tt> |
| parameters, and reference types work by instanceof. |
| </p><p> |
| There are two special cases: If the exposed value is typed to |
| <tt>Object</tt>, then the advice is not constrained by |
| that type: the actual return value is converted to an object |
| type for the body of the advice: <tt>int</tt> values |
| are represented as <tt>java.lang.Integer</tt> objects, |
| etc, and no value (from void methods, for example) is |
| represented as <tt>null</tt>. |
| </p><p> |
| Secondly, the <tt>null</tt> value is assignable to a |
| parameter <tt>T</tt> if the join point |
| <span class="emphasis"><i>could</i></span> return something of type |
| <tt>T</tt>. |
| </p><p> |
| Around advice runs in place of the join point it operates over, rather |
| than before or after it. Because around is allowed to return a value, it |
| must be declared with a return type, like a method. |
| </p><p> |
| Thus, a simple use of around advice is to make a particular method |
| constant: |
| </p><pre class="programlisting"> |
| aspect A { |
| int around(): call(int C.foo()) { |
| return 3; |
| } |
| } |
| </pre><p> |
| Within the body of around advice, though, the computation of the original |
| join point can be executed with the special syntax |
| </p><pre class="programlisting"> |
| proceed( ... ) |
| </pre><p> |
| The proceed form takes as arguments the context exposed by the around's |
| pointcut, and returns whatever the around is declared to return. So the |
| following around advice will double the second argument to |
| <tt>foo</tt> whenever it is called, and then halve its result: |
| </p><pre class="programlisting"> |
| aspect A { |
| int around(int i): call(int C.foo(Object, int)) && args(i) { |
| int newi = proceed(i*2) |
| return newi/2; |
| } |
| } |
| </pre><p> |
| If the return value of around advice is typed to |
| <tt>Object</tt>, then the result of proceed is converted to an |
| object representation, even if it is originally a primitive value. And |
| when the advice returns an Object value, that value is converted back to |
| whatever representation it was originally. So another way to write the |
| doubling and halving advice is: |
| </p><pre class="programlisting"> |
| aspect A { |
| Object around(int i): call(int C.foo(Object, int)) && args(i) { |
| Integer newi = (Integer) proceed(i*2) |
| return new Integer(newi.intValue() / 2); |
| } |
| } |
| </pre><p> |
| Any occurence of <tt>proceed(..)</tt> within the body of |
| around advice is treated as the special proceed form (even if the |
| aspect defines a method named <tt>proceed</tt>) unless a |
| target other than the aspect instance is specified as the recipient of |
| the call. |
| For example, in the following program the first |
| call to proceed will be treated as a method call to |
| the <tt>ICanProceed</tt> instance, whereas the second call to |
| proceed is treated as the special proceed form. |
| </p><pre class="programlisting"> |
| aspect A { |
| Object around(ICanProceed canProceed) : execution(* *(..)) && this(canProceed) { |
| canProceed.proceed(); // a method call |
| return proceed(canProceed); // the special proceed form |
| } |
| |
| private Object proceed(ICanProceed canProceed) { |
| // this method cannot be called from inside the body of around advice in |
| // the aspect |
| } |
| } |
| </pre><p> |
| In all kinds of advice, the parameters of the advice behave exactly like |
| method parameters. In particular, assigning to any parameter affects |
| only the value of the parameter, not the value that it came from. This |
| means that |
| </p><pre class="programlisting"> |
| aspect A { |
| after() returning (int i): call(int C.foo()) { |
| i = i * 2; |
| } |
| } |
| </pre><p> |
| will <span class="emphasis"><i>not</i></span> double the returned value of the advice. |
| Rather, it will double the local parameter. Changing the values of |
| parameters or return values of join points can be done by using around |
| advice. |
| </p><div class="sect2"><a name="advice-modifiers"></a><div class="titlepage"><div><h3 class="title"><a name="advice-modifiers"></a>Advice modifiers</h3></div></div><p> |
| The <tt>strictfp</tt> modifier is the only modifier allowed |
| on advice, and it has the effect of making all floating-point |
| expressions within the advice be FP-strict. |
| </p></div><div class="sect2"><a name="advice-and-checked-exceptions"></a><div class="titlepage"><div><h3 class="title"><a name="advice-and-checked-exceptions"></a>Advice and checked exceptions</h3></div></div><p> |
| An advice declaration must include a <tt>throws</tt> clause |
| listing the checked exceptions the body may throw. This list of |
| checked exceptions must be compatible with each target join point |
| of the advice, or an error is signalled by the compiler. |
| </p><p> |
| For example, in the following declarations: |
| </p><pre class="programlisting"> |
| import java.io.FileNotFoundException; |
| |
| class C { |
| int i; |
| |
| int getI() { return i; } |
| } |
| |
| aspect A { |
| before(): get(int C.i) { |
| throw new FileNotFoundException(); |
| } |
| before() throws FileNotFoundException: get(int C.i) { |
| throw new FileNotFoundException(); |
| } |
| } |
| </pre><p> |
| both pieces of advice are illegal. The first because the body throws |
| an undeclared checked exception, and the second because field get join |
| points cannot throw <tt>FileNotFoundException</tt>s. |
| </p><p> The exceptions that each kind of join point in AspectJ may throw are: |
| </p><div class="variablelist"><dl><dt><a name="d0e6208"></a><span class="term">method call and execution</span></dt><dd> |
| the checked exceptions declared by the target method's |
| <tt>throws</tt> clause. |
| </dd><dt><a name="d0e6216"></a><span class="term">constructor call and execution</span></dt><dd> |
| the checked exceptions declared by the target constructor's |
| <tt>throws</tt> clause. |
| </dd><dt><a name="d0e6224"></a><span class="term">field get and set</span></dt><dd> |
| no checked exceptions can be thrown from these join points. |
| </dd><dt><a name="d0e6229"></a><span class="term">exception handler execution</span></dt><dd> |
| the exceptions that can be thrown by the target exception handler. |
| </dd><dt><a name="d0e6234"></a><span class="term">static initializer execution</span></dt><dd> |
| no checked exceptions can be thrown from these join points. |
| </dd><dt><a name="d0e6239"></a><span class="term">pre-initialization and initialization</span></dt><dd> |
| any exception that is in the throws clause of |
| <span class="emphasis"><i>all</i></span> constructors of the initialized class. |
| </dd><dt><a name="d0e6247"></a><span class="term">advice execution</span></dt><dd> |
| any exception that is in the throws clause of the advice. |
| </dd></dl></div></div><div class="sect2"><a name="advice-precedence"></a><div class="titlepage"><div><h3 class="title"><a name="advice-precedence"></a>Advice precedence</h3></div></div><p> |
| Multiple pieces of advice may apply to the same join point. In such |
| cases, the resolution order of the advice is based on advice |
| precedence. |
| </p><div class="sect3"><a name="d0e6257"></a><div class="titlepage"><div><h4 class="title"><a name="d0e6257"></a>Determining precedence</h4></div></div><p>There are a number of rules that determine whether a particular |
| piece of advice has precedence over another when they advise the same |
| join point. </p><p>If the two pieces of advice are defined in different aspects, |
| then there are three cases: </p><div class="itemizedlist"><ul><li><a name="d0e6265"></a>If aspect A is matched earlier than aspect B in some |
| <tt>declare precedence</tt> form, then all advice in |
| concrete aspect A has precedence over all advice in concrete aspect B |
| when they are on the same join point. </li><li><a name="d0e6270"></a> |
| Otherwise, if aspect A is a subaspect of aspect B, then all advice |
| defined in A has precedence over all advice defined in |
| B. So, unless otherwise specified with |
| <tt>declare precedence</tt>, advice in a subaspect |
| has precedence over advice in a superaspect. |
| </li><li><a name="d0e6275"></a> |
| Otherwise, if two pieces of advice are defined in two different |
| aspects, it is undefined which one has precedence. |
| </li></ul></div><p>If the two pieces of advice are defined in the same aspect, then |
| there are two cases: </p><div class="itemizedlist"><ul><li><a name="d0e6280"></a>If either are <tt>after</tt> advice, then the one that |
| appears later in the aspect has precedence over the one that appears |
| earlier. </li><li><a name="d0e6285"></a>Otherwise, then the one that appears earlier in the aspect |
| has precedence over the one that appears later. |
| </li></ul></div><p>These rules can lead to circularity, such as</p><pre class="programlisting"> |
| aspect A { |
| before(): execution(void main(String[] args)) {} |
| after(): execution(void main(String[] args)) {} |
| before(): execution(void main(String[] args)) {} |
| } |
| </pre><p>such circularities will result in errors signalled by the compiler. </p></div><div class="sect3"><a name="d0e6293"></a><div class="titlepage"><div><h4 class="title"><a name="d0e6293"></a>Effects of precedence</h4></div></div><p>At a particular join point, advice is ordered by precedence.</p><p>A piece of <tt>around</tt> advice controls whether |
| advice of lower precedence will run by calling |
| <tt>proceed</tt>. The call to <tt>proceed</tt> |
| will run the advice with next precedence, or the computation under the |
| join point if there is no further advice. </p><p>A piece of <tt>before</tt> advice can prevent advice of |
| lower precedence from running by throwing an exception. If it returns |
| normally, however, then the advice of the next precedence, or the |
| computation under the join pint if there is no further advice, will run. |
| </p><p>Running <tt>after returning</tt> advice will run the |
| advice of next precedence, or the computation under the join point if |
| there is no further advice. Then, if that computation returned |
| normally, the body of the advice will run. </p><p>Running <tt>after throwing</tt> advice will run the |
| advice of next precedence, or the computation under the join |
| point if there is no further advice. Then, if that computation threw |
| an exception of an appropriate type, the body of the advice will |
| run. </p><p>Running <tt>after</tt> advice will run the advice of |
| next precedence, or the computation under the join point if |
| there is no further advice. Then the body of the advice will |
| run. </p></div></div><div class="sect2"><a name="reflective-access-to-the-join-point"></a><div class="titlepage"><div><h3 class="title"><a name="reflective-access-to-the-join-point"></a>Reflective access to the join point</h3></div></div><p> |
| Three special variables are visible within bodies of advice |
| and within <tt>if()</tt> pointcut expressions: |
| <tt>thisJoinPoint</tt>, |
| <tt>thisJoinPointStaticPart</tt>, and |
| <tt>thisEnclosingJoinPointStaticPart</tt>. Each is bound to |
| an object that encapsulates some of the context of the advice's current |
| or enclosing join point. These variables exist because some pointcuts |
| may pick out very large collections of join points. For example, the |
| pointcut |
| </p><pre class="programlisting"> |
| pointcut publicCall(): call(public * *(..)); |
| </pre><p> |
| picks out calls to many methods. Yet the body of advice over this |
| pointcut may wish to have access to the method name or parameters of a |
| particular join point. |
| </p><p> |
| <tt>thisJoinPoint</tt> is bound to a complete join point |
| object. |
| |
| </p><p> |
| <tt>thisJoinPointStaticPart</tt> is bound to a part of the |
| join point object that includes less information, but for which no |
| memory allocation is required on each execution of the advice. It is |
| equivalent to <tt>thisJoinPoint.getStaticPart()</tt>. |
| </p><p> |
| <tt>thisEnclosingJoinPointStaticPart</tt> is bound to the |
| static part of the join point enclosing the current join point. Only |
| the static part of this enclosing join point is available through this |
| mechanism. |
| </p><p> |
| Standard Java reflection uses objects from the |
| <tt>java.lang.reflect</tt> hierarchy to build up its |
| reflective objects. Similarly, AspectJ join point objects have types |
| in a type hierarchy. The type of objects bound to |
| <tt>thisJoinPoint</tt> is |
| <tt>org.aspectj.lang.JoinPoint</tt>, while |
| <tt>thisStaticJoinPoint</tt> is bound to objects of interface |
| type <tt>org.aspectj.lang.JoinPoint.StaticPart</tt>. |
| </p></div></div><div class="navfooter"><hr><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="semantics-pointcuts.html">Prev</a> </td><td width="20%" align="center"><a accesskey="h" href="index.html">Home</a></td><td width="40%" align="right"> <a accesskey="n" href="semantics-declare.html">Next</a></td></tr><tr><td width="40%" align="left">Pointcuts </td><td width="20%" align="center"><a accesskey="u" href="semantics.html">Up</a></td><td width="40%" align="right"> Static crosscutting</td></tr></table></div></body></html> |