|
|
@@ -58,18 +58,6 @@ |
|
|
|
public class Foo {} |
|
|
|
]]></programlisting> |
|
|
|
|
|
|
|
|
|
|
|
<para>Privileged aspects are not supported by the annotation style</para> |
|
|
|
<!-- |
|
|
|
<programlisting><![CDATA[ |
|
|
|
@Aspect(isPrivileged=true) |
|
|
|
public class Foo {} |
|
|
|
|
|
|
|
is equivalent to... |
|
|
|
|
|
|
|
public privileged aspect Foo {} |
|
|
|
]]></programlisting> |
|
|
|
--> |
|
|
|
<para>To specify an aspect an aspect instantiation model (the default is |
|
|
|
singleton), provide the perclause as the |
|
|
|
<literal>@Aspect</literal> value. |
|
|
@@ -79,12 +67,32 @@ |
|
|
|
<programlisting><![CDATA[ |
|
|
|
@Aspect("perthis(execution(* abc..*(..)))") |
|
|
|
public class Foo {} |
|
|
|
]]></programlisting> |
|
|
|
|
|
|
|
is equivalent to... |
|
|
|
<para>is equivalent to...</para> |
|
|
|
|
|
|
|
<programlisting><![CDATA[ |
|
|
|
public aspect Foo perthis(execution(* abc..*(..))) {} |
|
|
|
]]></programlisting> |
|
|
|
|
|
|
|
<sect2> |
|
|
|
<title>Limitations</title> |
|
|
|
|
|
|
|
<para>Privileged aspects are not supported by the annotation style.</para> |
|
|
|
<!-- |
|
|
|
<programlisting><![CDATA[ |
|
|
|
@Aspect(isPrivileged=true) |
|
|
|
public class Foo {} |
|
|
|
]]></programlisting> |
|
|
|
|
|
|
|
<para>is equivalent to...</para> |
|
|
|
|
|
|
|
<programlisting><![CDATA[ |
|
|
|
public privileged aspect Foo {} |
|
|
|
]]></programlisting> |
|
|
|
--> |
|
|
|
</sect2> |
|
|
|
|
|
|
|
</sect1> |
|
|
|
|
|
|
|
<sect1 id="ataspectj-pcadvice"> |
|
|
@@ -120,48 +128,52 @@ |
|
|
|
</para> |
|
|
|
|
|
|
|
<para> |
|
|
|
There is one special case to the general rule for when you use |
|
|
|
<literal>if()</literal> pointcut |
|
|
|
as detailled in the next section. |
|
|
|
The <literal>if()</literal> pointcut is treated specially and is discussed in a later section. |
|
|
|
</para> |
|
|
|
|
|
|
|
<para>A simple example:</para> |
|
|
|
<para>Here is a simple example of a pointcut declaration in both code and @AspectJ styles:</para> |
|
|
|
|
|
|
|
<programlisting><![CDATA[ |
|
|
|
@Pointcut("call(* *.*(..))") |
|
|
|
void anyCall() {} |
|
|
|
]]></programlisting> |
|
|
|
|
|
|
|
is equivalent to... |
|
|
|
<para>is equivalent to...</para> |
|
|
|
|
|
|
|
<programlisting><![CDATA[ |
|
|
|
pointcut anyCall() : call(* *.*(..)); |
|
|
|
]]></programlisting> |
|
|
|
|
|
|
|
|
|
|
|
<para>An example with formal bindings:</para> |
|
|
|
<para>When binding arguments, simply declare the arguments as normal in the annotated method:</para> |
|
|
|
|
|
|
|
<programlisting><![CDATA[ |
|
|
|
@Pointcut("call(* *.*(int)) && args(i) && target(callee)") |
|
|
|
void someCall(int i, Foo callee) {} |
|
|
|
]]></programlisting> |
|
|
|
|
|
|
|
is equivalent to... |
|
|
|
<para>is equivalent to...</para> |
|
|
|
|
|
|
|
<programlisting><![CDATA[ |
|
|
|
pointcut anyCall(int i, Foo callee) : call(* *.*(int)) && args(i) && target(callee); |
|
|
|
]]></programlisting> |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<para>An example with modifiers (it is also good to remember that Java 5 annotations are not inherited):</para> |
|
|
|
|
|
|
|
<programlisting><![CDATA[ |
|
|
|
@Pointcut("") |
|
|
|
protected abstract void anyCall(); |
|
|
|
]]></programlisting> |
|
|
|
|
|
|
|
is equivalent to... |
|
|
|
<para>is equivalent to...</para> |
|
|
|
|
|
|
|
<programlisting><![CDATA[ |
|
|
|
protected abstract pointcut anyCall(); |
|
|
|
]]></programlisting> |
|
|
|
|
|
|
|
<sect3> |
|
|
|
<title>Type references inside @AspectJ annotations</title> |
|
|
|
|
|
|
|
<para> |
|
|
|
Using the code style, types referenced in pointcut expressions are |
|
|
|
resolved with respect to the imported types in the compilation unit. |
|
|
@@ -170,7 +182,7 @@ |
|
|
|
to be fully qualified if they are not by default visible to the |
|
|
|
declaring type (outside of the declaring package and |
|
|
|
<literal>java.lang</literal>). This |
|
|
|
to not apply to type patterns with wildcards, which are always resolved |
|
|
|
does not apply to type patterns with wildcards, which are always resolved |
|
|
|
in a global scope. |
|
|
|
</para> |
|
|
|
|
|
|
@@ -213,16 +225,14 @@ |
|
|
|
} |
|
|
|
]]></programlisting> |
|
|
|
|
|
|
|
<para>The |
|
|
|
<literal>value</literal> attribute of the |
|
|
|
<literal>Pointcut</literal> declaration may contain any valid |
|
|
|
AspectJ pointcut declaration - though <literal>if()</literal> pointcut is a special case explained below. |
|
|
|
</para> |
|
|
|
</sect3> |
|
|
|
|
|
|
|
<para>The special case for the <literal>if()</literal> pointcut.</para> |
|
|
|
<sect3> |
|
|
|
<title>if() pointcut expressions</title> |
|
|
|
|
|
|
|
<para>In code style, it is possible to use the <literal>if(...)</literal> poincut to implement |
|
|
|
conditional pointcut whose residual if form will be evaluated at runtime. The <literal>if(...)</literal> |
|
|
|
<para>In code style, it is possible to use the <literal>if(...)</literal> poincut to define |
|
|
|
a conditional pointcut expression which will be evaluated at runtime for each candidate join point. |
|
|
|
The <literal>if(...)</literal> |
|
|
|
body can be any valid Java boolean expression, and can use any exposed formal, as well as the join point forms |
|
|
|
<literal>thisJoinPoint, thisJoinPointStaticPart and thisJoinPointEnclosingStaticPart</literal>. |
|
|
|
</para> |
|
|
@@ -230,7 +240,11 @@ |
|
|
|
<para> |
|
|
|
When using the annotation style, it would be really a pain to write a valid Java expression within |
|
|
|
the annotation value so the syntax differs sligthly, whilst providing the very same |
|
|
|
semantics and runtime behaviour. Take the following examples: |
|
|
|
semantics and runtime behaviour. An <literal>if()</literal> pointcut expression can be |
|
|
|
declared in an <literal>@Pointcut</literal>, but must either an empty body, or be one |
|
|
|
of the expression <literal>if(true)</literal> or <literal>if(false)</literal>. The annotated |
|
|
|
method must be public, static, and return a boolean. The body of the method contains the |
|
|
|
condition to be evaluated. For example: |
|
|
|
</para> |
|
|
|
|
|
|
|
<programlisting><![CDATA[ |
|
|
@@ -238,9 +252,11 @@ |
|
|
|
public static boolean someCallWithIfTest(int i) { |
|
|
|
return i > 0; |
|
|
|
} |
|
|
|
]]></programlisting> |
|
|
|
|
|
|
|
is equivalent to... |
|
|
|
<para>is equivalent to...</para> |
|
|
|
|
|
|
|
<programlisting><![CDATA[ |
|
|
|
pointcut someCallWithIfTest(int i) : call(* *.*(int)) && args(i) && if(i > 0); |
|
|
|
]]></programlisting> |
|
|
|
|
|
|
@@ -251,15 +267,15 @@ |
|
|
|
|
|
|
|
@Pointcut("call(* *.*(int)) && args(i) && if()") |
|
|
|
public static boolean someCallWithIfTest(int i, JoinPoint jp, JoinPoint.EnclosingStaticPart esjp) { |
|
|
|
// can call any kind of method (though this method is a static one) |
|
|
|
// any legal Java expression... |
|
|
|
return i > 0 |
|
|
|
&& jp.getSignature().getName.startsWith("doo") |
|
|
|
&& esjp.getSignature().getName().startsWith("test") |
|
|
|
&& COUNT++ < 10; |
|
|
|
} |
|
|
|
|
|
|
|
@Before("someCallWithIfTest(arg0, jp, enc)") // see how the pointcut is referenced: we obey its exact signature |
|
|
|
public void beforeAdviceWithRuntimeTest(int arg0, JoinPoint jp, JoinPoint.EnclosingStaticPart enc) { |
|
|
|
@Before("someCallWithIfTest(anInt, jp, enc)") |
|
|
|
public void beforeAdviceWithRuntimeTest(int anInt, JoinPoint jp, JoinPoint.EnclosingStaticPart enc) { |
|
|
|
//... |
|
|
|
} |
|
|
|
|
|
|
@@ -275,10 +291,10 @@ |
|
|
|
<para> |
|
|
|
It is thus possible with the annotation style to use the <literal>if()</literal> pointcut |
|
|
|
only within an <literal>@Pointcut</literal> expression. The <literal>if()</literal> must not contain any |
|
|
|
body. The so annotated <literal>@Pointcut</literal> method must then be of the form <literal>public static boolean</literal> |
|
|
|
body. The annotated <literal>@Pointcut</literal> method must then be of the form <literal>public static boolean</literal> |
|
|
|
and can use formal bindings as usual. |
|
|
|
Extra <emphasis>implicit</emphasis> (thus unbound) arguments of type JoinPoint, JoinPoint.StaticPart and JoinPoint.EnclosingStaticPart can also be used |
|
|
|
(they can't for regular pointcut without <literal>if()</literal> form). |
|
|
|
Extra <emphasis>implicit</emphasis> arguments of type JoinPoint, JoinPoint.StaticPart and JoinPoint.EnclosingStaticPart can also be used |
|
|
|
(this is not permitted for regular annotated pointcuts not using the <literal>if()</literal> form). |
|
|
|
</para> |
|
|
|
|
|
|
|
<para> |
|
|
@@ -287,6 +303,8 @@ |
|
|
|
You can thus write <literal>@Before("somePoincut() && if(false)")</literal>. |
|
|
|
</para> |
|
|
|
|
|
|
|
</sect3> |
|
|
|
|
|
|
|
</sect2> |
|
|
|
|
|
|
|
<sect2> |
|
|
@@ -312,27 +330,31 @@ |
|
|
|
<para>A method that has an advice annotation is treated exactly as an |
|
|
|
advice declaration by AspectJ's weaver. This includes the join points that |
|
|
|
arise when the advice is executed (an adviceexecution join point, not a |
|
|
|
method execution join point), and the restriction that advice cannot be |
|
|
|
invoked explicitly (the weaver will issue an error if an advice method |
|
|
|
is explicitly invoked).</para> |
|
|
|
method execution join point).</para> |
|
|
|
|
|
|
|
<para>The following example shows a simple before advice declaration in |
|
|
|
both styles:</para> |
|
|
|
|
|
|
|
<programlisting><![CDATA[ |
|
|
|
before() : call(* org.aspectprogrammer..*(..)) && this(Foo) { |
|
|
|
<programlisting><![CDATA[ |
|
|
|
@Before("call(* org.aspectprogrammer..*(..)) && this(Foo)") |
|
|
|
public void callFromFoo() { |
|
|
|
System.out.println("Call from Foo"); |
|
|
|
} |
|
|
|
]]></programlisting> |
|
|
|
|
|
|
|
is equivalent to... |
|
|
|
<para>is equivalent to...</para> |
|
|
|
|
|
|
|
@Before("call(* org.aspectprogrammer..*(..)) && this(Foo)") |
|
|
|
public void callFromFoo() { |
|
|
|
<programlisting><![CDATA[ |
|
|
|
before() : call(* org.aspectprogrammer..*(..)) && this(Foo) { |
|
|
|
System.out.println("Call from Foo"); |
|
|
|
} |
|
|
|
]]></programlisting> |
|
|
|
]]></programlisting> |
|
|
|
|
|
|
|
|
|
|
|
<para>Notice one slight difference between the two advice declarations: in |
|
|
|
<!-- |
|
|
|
AMC: enhanced adviceexecution pointcuts and @AdviceName will most likely not make AJ5 1.5.0 |
|
|
|
|
|
|
|
<para>Notice one slight difference between the two advice declarations: in |
|
|
|
the annotation style, the advice has a name, "callFromFoo". Even though |
|
|
|
advice cannot be invoked explicitly, this name is useful in join point |
|
|
|
matching when advising advice execution. For this reason, and to preserve |
|
|
@@ -354,20 +376,23 @@ |
|
|
|
System.out.println("Call from Foo"); |
|
|
|
} |
|
|
|
]]></programlisting> |
|
|
|
|
|
|
|
--> |
|
|
|
|
|
|
|
<para>If the advice body needs to know which particular |
|
|
|
<literal>Foo</literal> |
|
|
|
was doing the calling, just add a parameter to the advice declaration. |
|
|
|
<literal>Foo</literal> instance |
|
|
|
is making the call, just add a parameter to the advice declaration. |
|
|
|
</para> |
|
|
|
|
|
|
|
<programlisting><![CDATA[ |
|
|
|
@AdviceName("callFromFoo") |
|
|
|
before(Foo foo) : call(* org.aspectprogrammer..*(..)) && this(foo) { |
|
|
|
System.out.println("Call from Foo: " + foo); |
|
|
|
} |
|
|
|
]]></programlisting> |
|
|
|
|
|
|
|
is equivalent to... |
|
|
|
<para>can be written as:</para> |
|
|
|
|
|
|
|
<programlisting><![CDATA[ |
|
|
|
@Before("call(* org.aspectprogrammer..*(..)) && this(foo)") |
|
|
|
public void callFromFoo(Foo foo) { |
|
|
|
System.out.println("Call from Foo: " + foo); |
|
|
@@ -385,21 +410,22 @@ |
|
|
|
</para> |
|
|
|
|
|
|
|
<programlisting><![CDATA[ |
|
|
|
@AdviceName("callFromFoo") |
|
|
|
before(Foo foo) : call(* org.aspectprogrammer..*(..)) && this(foo) { |
|
|
|
System.out.println("Call from Foo: " + foo + " at " |
|
|
|
+ thisJoinPoint); |
|
|
|
} |
|
|
|
|
|
|
|
is equivalent to... |
|
|
|
|
|
|
|
@Before("call(* org.aspectprogrammer..*(..)) && this(foo)") |
|
|
|
public void callFromFoo(JoinPoint thisJoinPoint, Foo foo) { |
|
|
|
System.out.println("Call from Foo: " + foo + " at " |
|
|
|
+ thisJoinPoint); |
|
|
|
} |
|
|
|
]]></programlisting> |
|
|
|
|
|
|
|
<para>is equivalent to...</para> |
|
|
|
|
|
|
|
<programlisting><![CDATA[ |
|
|
|
before(Foo foo) : call(* org.aspectprogrammer..*(..)) && this(foo) { |
|
|
|
System.out.println("Call from Foo: " + foo + " at " |
|
|
|
+ thisJoinPoint); |
|
|
|
} |
|
|
|
]]></programlisting> |
|
|
|
|
|
|
|
<para>Advice that needs all three variables would be declared:</para> |
|
|
|
|
|
|
|
<programlisting><![CDATA[ |
|
|
@@ -438,23 +464,25 @@ |
|
|
|
</para> |
|
|
|
|
|
|
|
<programlisting><![CDATA[ |
|
|
|
after() returning : criticalOperation() { |
|
|
|
@AfterReturning("criticalOperation()") |
|
|
|
public void phew() { |
|
|
|
System.out.println("phew"); |
|
|
|
} |
|
|
|
|
|
|
|
after() returning(Foo f) : call(Foo+.new(..)) { |
|
|
|
@AfterReturning(pointcut="call(Foo+.new(..))",returning="f") |
|
|
|
public void itsAFoo(Foo f) { |
|
|
|
System.out.println("It's a Foo: " + f); |
|
|
|
} |
|
|
|
]]></programlisting> |
|
|
|
|
|
|
|
can be written as... |
|
|
|
<para>is equivalent to...</para> |
|
|
|
|
|
|
|
@AfterReturning("criticalOperation()") |
|
|
|
public void phew() { |
|
|
|
<programlisting><![CDATA[ |
|
|
|
after() returning : criticalOperation() { |
|
|
|
System.out.println("phew"); |
|
|
|
} |
|
|
|
|
|
|
|
@AfterReturning(pointcut="call(Foo+.new(..))",returning="f") |
|
|
|
public void itsAFoo(Foo f) { |
|
|
|
after() returning(Foo f) : call(Foo+.new(..)) { |
|
|
|
System.out.println("It's a Foo: " + f); |
|
|
|
} |
|
|
|
]]></programlisting> |
|
|
@@ -507,16 +535,6 @@ |
|
|
|
<para>Here's an example that uses parameters for the proceed call:</para> |
|
|
|
|
|
|
|
<programlisting><![CDATA[ |
|
|
|
public aspect ProceedAspect { |
|
|
|
pointcut setAge(int i): call(* setAge(..)) && args(i); |
|
|
|
|
|
|
|
Object around(int i): setAge(i) { |
|
|
|
return proceed(i*2); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
can be written as... |
|
|
|
|
|
|
|
@Aspect |
|
|
|
public class ProceedAspect { |
|
|
|
|
|
|
@@ -530,9 +548,24 @@ |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
Note that the ProceedingJoinPoint does not need to be passed as the proceed(..) arguments. |
|
|
|
]]></programlisting> |
|
|
|
|
|
|
|
<para>is equivalent to:</para> |
|
|
|
|
|
|
|
<programlisting><![CDATA[ |
|
|
|
public aspect ProceedAspect { |
|
|
|
pointcut setAge(int i): call(* setAge(..)) && args(i); |
|
|
|
|
|
|
|
Object around(int i): setAge(i) { |
|
|
|
return proceed(i*2); |
|
|
|
} |
|
|
|
} |
|
|
|
]]></programlisting> |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<para>Note that the ProceedingJoinPoint does not need to be passed to the proceed(..) arguments. |
|
|
|
</para> |
|
|
|
</sect2> |
|
|
|
|
|
|
|
</sect1> |
|
|
@@ -540,6 +573,9 @@ |
|
|
|
<sect1 id="ataspectj-itds"> |
|
|
|
<title>Inter-type Declarations</title> |
|
|
|
|
|
|
|
<para><emphasis>The features described in this section will not be supported until the |
|
|
|
AspectJ 5 M4 milestone build.</emphasis></para> |
|
|
|
|
|
|
|
<para> |
|
|
|
Inter-type declarations are challenging to support using an annotation style. |
|
|
|
It's very important to preserve the exact same semantics between the code style |
|
|
@@ -703,8 +739,8 @@ |
|
|
|
]]></programlisting> |
|
|
|
|
|
|
|
<para> |
|
|
|
Note: Declare annotation is not available in AspectJ 1.5 M3 and syntax might change |
|
|
|
when it will be available. |
|
|
|
<emphasis>Note: Declare annotation is not available in AspectJ 1.5 M3 and syntax may change |
|
|
|
when the design and implementation is complete.</emphasis> |
|
|
|
</para> |
|
|
|
|
|
|
|
<para>We also support annotation style declarations for declare warning and |