/usr/share/doc/aspectj-doc/progguide/semantics-advice.html is in aspectj-doc 1.8.8-1.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 | <html><head><meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"><title>Advice</title><link rel="stylesheet" type="text/css" href="aspectj-docs.css"><meta name="generator" content="DocBook XSL Stylesheets V1.79.1"><link rel="home" href="index.html" title="The AspectJTM Programming Guide"><link rel="up" href="semantics.html" title="Appendix B. Language Semantics"><link rel="prev" 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"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="semantics-advice"></a>Advice</h2></div></div></div><p>
Each piece of advice is of the form
</p><div class="blockquote"><blockquote class="blockquote"><code class="literal">[ strictfp ] <em class="replaceable"><code>AdviceSpec</code></em> [
throws <em class="replaceable"><code>TypeList</code></em> ] :
<em class="replaceable"><code>Pointcut</code></em> {
<em class="replaceable"><code>Body</code></em> } </code></blockquote></div><p>
where <em class="replaceable"><code>AdviceSpec</code></em> is one of
</p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem"><code class="literal">before( <em class="replaceable"><code>Formals</code></em> ) </code></li><li class="listitem"><code class="literal">after( <em class="replaceable"><code>Formals</code></em> ) returning
[ ( <em class="replaceable"><code>Formal</code></em> ) ] </code></li><li class="listitem"><code class="literal">after( <em class="replaceable"><code>Formals</code></em> ) throwing [
( <em class="replaceable"><code>Formal</code></em> ) ] </code></li><li class="listitem"><code class="literal">after( <em class="replaceable"><code>Formals</code></em> ) </code></li><li class="listitem"><code class="literal"><em class="replaceable"><code>Type</code></em>
around( <em class="replaceable"><code>Formals</code></em> )</code></li></ul></div><p>
and where <em class="replaceable"><code>Formal</code></em> refers to a
variable binding like those used for method parameters,
of the form
<code class="literal"><em class="replaceable"><code>Type</code></em></code>
<code class="literal"><em class="replaceable"><code>Variable-Name</code></em></code>,
and <em class="replaceable"><code>Formals</code></em> refers to a comma-delimited
list of <em class="replaceable"><code>Formal</code></em>.
</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
<code class="literal">instanceof</code>-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
<code class="literal">byte</code> value is assignable to a
<code class="literal">short</code> parameter but not vice-versa, an
<code class="literal">int</code> is assignable to a
<code class="literal">float</code> parameter, <code class="literal">boolean</code>
values are only assignable to <code class="literal">boolean</code>
parameters, and reference types work by instanceof.
</p><p>
There are two special cases: If the exposed value is typed to
<code class="literal">Object</code>, 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: <code class="literal">int</code> values
are represented as <code class="literal">java.lang.Integer</code> objects,
etc, and no value (from void methods, for example) is
represented as <code class="literal">null</code>.
</p><p>
Secondly, the <code class="literal">null</code> value is assignable to a
parameter <code class="literal">T</code> if the join point
<span class="emphasis"><em>could</em></span> return something of type
<code class="literal">T</code>.
</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
<code class="literal">foo</code> 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
<code class="literal">Object</code>, 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 <code class="literal">proceed(..)</code> within the body of around
advice is treated as the special proceed form (even if the
aspect defines a method named <code class="literal">proceed</code>), 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 <code class="literal">ICanProceed</code> 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"><em>not</em></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><p>
With <code class="literal">proceed(..)</code> it is possible to change the values
used by less-precedent advice and the underlying join point by supplying
different values for the variables. For example, this aspect replaces
the string bound to <code class="literal">s</code> in the named pointcut
<code class="literal">privateData</code>:
</p><pre class="programlisting">
aspect A {
Object around(String s): MyPointcuts.privateData(s) {
return proceed("private data");
}
}
</pre><p>
If you replace an argument to <code class="literal">proceed(..)</code>, you can cause
a <code class="literal">ClassCastException</code> at runtime when the argument
refers to a supertype of the actual type and you do not supply a
reference of the actual type. In the following aspect, the
around advice replaces the declared target <code class="literal">List</code>
with an <code class="literal">ArrayList</code>. This is valid code at
compile-time since the types match.
</p><pre class="programlisting">
import java.util.*;
aspect A {
Object around(List list): call(* List+.*()) && target(list) {
return proceed(new ArrayList());
}
}
</pre><p>
But imagine a simple program where the actual target is
<code class="literal">LinkedList</code>. In this case, the advice would cause a
<code class="literal">ClassCastException</code> at runtime, and
<code class="literal">peek()</code> is not declared in <code class="literal">ArrayList</code>.
</p><pre class="programlisting">
public class Test {
public static void main(String[] args) {
new LinkedList().peek();
}
}
</pre><p>
The <code class="literal">ClassCastException</code> can occur even in situations
where it appears to be unnecessary, e.g., if the program is changed to
call <code class="literal">size()</code>, declared in <code class="literal">List</code>:
</p><pre class="programlisting">
public class Test {
public static void main(String[] args) {
new LinkedList().size();
}
}
</pre><p>
There will still be a <code class="literal">ClassCastException</code> because
it is impossible to prove that there won't be a runtime binary-compatible
change in the hierarchy of <code class="literal">LinkedList</code> or some
other advice on the join point that requires a
<code class="literal">LinkedList</code>.
</p><div class="sect2"><div class="titlepage"><div><div><h3 class="title"><a name="advice-modifiers"></a>Advice modifiers</h3></div></div></div><p>
The <code class="literal">strictfp</code> 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"><div class="titlepage"><div><div><h3 class="title"><a name="advice-and-checked-exceptions"></a>Advice and checked exceptions</h3></div></div></div><p>
An advice declaration must include a <code class="literal">throws</code> 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 <code class="literal">FileNotFoundException</code>s.
</p><p> The exceptions that each kind of join point in AspectJ may throw are:
</p><div class="variablelist"><dl class="variablelist"><dt><span class="term">method call and execution</span></dt><dd>
the checked exceptions declared by the target method's
<code class="literal">throws</code> clause.
</dd><dt><span class="term">constructor call and execution</span></dt><dd>
the checked exceptions declared by the target constructor's
<code class="literal">throws</code> clause.
</dd><dt><span class="term">field get and set</span></dt><dd>
no checked exceptions can be thrown from these join points.
</dd><dt><span class="term">exception handler execution</span></dt><dd>
the exceptions that can be thrown by the target exception handler.
</dd><dt><span class="term">static initializer execution</span></dt><dd>
no checked exceptions can be thrown from these join points.
</dd><dt><span class="term">pre-initialization and initialization</span></dt><dd>
any exception that is in the throws clause of
<span class="emphasis"><em>all</em></span> constructors of the initialized class.
</dd><dt><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"><div class="titlepage"><div><div><h3 class="title"><a name="advice-precedence"></a>Advice precedence</h3></div></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"><div class="titlepage"><div><div><h4 class="title"><a name="idp52368496"></a>Determining precedence</h4></div></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 class="itemizedlist" style="list-style-type: disc; "><li class="listitem">If aspect A is matched earlier than aspect B in some
<code class="literal">declare precedence</code> 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 class="listitem">
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
<code class="literal">declare precedence</code>, advice in a subaspect
has precedence over advice in a superaspect.
</li><li class="listitem">
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 class="itemizedlist" style="list-style-type: disc; "><li class="listitem">If either are <code class="literal">after</code> advice, then the one that
appears later in the aspect has precedence over the one that appears
earlier. </li><li class="listitem">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"><div class="titlepage"><div><div><h4 class="title"><a name="idp52378432"></a>Effects of precedence</h4></div></div></div><p>At a particular join point, advice is ordered by precedence.</p><p>A piece of <code class="literal">around</code> advice controls whether
advice of lower precedence will run by calling
<code class="literal">proceed</code>. The call to <code class="literal">proceed</code>
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 <code class="literal">before</code> 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 <code class="literal">after returning</code> 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 <code class="literal">after throwing</code> 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 <code class="literal">after</code> 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"><div class="titlepage"><div><div><h3 class="title"><a name="reflective-access-to-the-join-point"></a>Reflective access to the join point</h3></div></div></div><p>
Three special variables are visible within bodies of advice
and within <code class="literal">if()</code> pointcut expressions:
<code class="literal">thisJoinPoint</code>,
<code class="literal">thisJoinPointStaticPart</code>, and
<code class="literal">thisEnclosingJoinPointStaticPart</code>. 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>
<code class="literal">thisJoinPoint</code> is bound to a complete join point
object.
</p><p>
<code class="literal">thisJoinPointStaticPart</code> 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 <code class="literal">thisJoinPoint.getStaticPart()</code>.
</p><p>
<code class="literal">thisEnclosingJoinPointStaticPart</code> 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
<code class="literal">java.lang.reflect</code> hierarchy to build up its
reflective objects. Similarly, AspectJ join point objects have types
in a type hierarchy. The type of objects bound to
<code class="literal">thisJoinPoint</code> is
<code class="literal">org.aspectj.lang.JoinPoint</code>, while
<code class="literal">thisStaticJoinPoint</code> is bound to objects of interface
type <code class="literal">org.aspectj.lang.JoinPoint.StaticPart</code>.
</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="u" href="semantics.html">Up</a></td><td width="40%" align="right"> <a accesskey="n" href="semantics-declare.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">Pointcuts </td><td width="20%" align="center"><a accesskey="h" href="index.html">Home</a></td><td width="40%" align="right" valign="top"> Static crosscutting</td></tr></table></div></body></html>
|