aboutsummaryrefslogtreecommitdiffstats
path: root/docs/adk15ProgGuideDB/ataspectj.xml
diff options
context:
space:
mode:
Diffstat (limited to 'docs/adk15ProgGuideDB/ataspectj.xml')
-rw-r--r--docs/adk15ProgGuideDB/ataspectj.xml821
1 files changed, 407 insertions, 414 deletions
diff --git a/docs/adk15ProgGuideDB/ataspectj.xml b/docs/adk15ProgGuideDB/ataspectj.xml
index 0ac475cc6..7f8152d9c 100644
--- a/docs/adk15ProgGuideDB/ataspectj.xml
+++ b/docs/adk15ProgGuideDB/ataspectj.xml
@@ -42,15 +42,15 @@
</para>
<programlisting><![CDATA[
- @Aspect
- public class Foo {}
- ]]></programlisting>
+@Aspect
+public class Foo {}
+]]></programlisting>
<para>Is equivalent to:</para>
<programlisting><![CDATA[
- public aspect Foo {}
- ]]></programlisting>
+public aspect Foo {}
+]]></programlisting>
<para>To specify an aspect an aspect instantiation model (the default is
singleton), provide the perclause as the
@@ -60,15 +60,15 @@
</para>
<programlisting><![CDATA[
- @Aspect("perthis(execution(* abc..*(..)))")
- public class Foo {}
- ]]></programlisting>
+@Aspect("perthis(execution(* abc..*(..)))")
+public class Foo {}
+]]></programlisting>
<para>is equivalent to...</para>
<programlisting><![CDATA[
- public aspect Foo perthis(execution(* abc..*(..))) {}
- ]]></programlisting>
+public aspect Foo perthis(execution(* abc..*(..))) {}
+]]></programlisting>
<sect2 id="limitations" xreflabel="limitations">
<title>Limitations</title>
@@ -76,15 +76,15 @@
<para>Privileged aspects are not supported by the annotation style.</para>
<!--
<programlisting><![CDATA[
- @Aspect(isPrivileged=true)
- public class Foo {}
- ]]></programlisting>
+@Aspect(isPrivileged=true)
+public class Foo {}
+]]></programlisting>
<para>is equivalent to...</para>
<programlisting><![CDATA[
- public privileged aspect Foo {}
- ]]></programlisting>
+public privileged aspect Foo {}
+]]></programlisting>
-->
</sect2>
@@ -136,44 +136,44 @@
<para>Here is a simple example of a pointcut declaration in both code and @AspectJ styles:</para>
<programlisting><![CDATA[
- @Pointcut("call(* *.*(..))")
- void anyCall() {}
- ]]></programlisting>
+@Pointcut("call(* *.*(..))")
+void anyCall() {}
+]]></programlisting>
<para>is equivalent to...</para>
<programlisting><![CDATA[
- pointcut anyCall() : call(* *.*(..));
- ]]></programlisting>
+pointcut anyCall() : call(* *.*(..));
+]]></programlisting>
<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 anyCall(int i, Foo callee) {}
- ]]></programlisting>
+@Pointcut("call(* *.*(int)) && args(i) && target(callee)")
+void anyCall(int i, Foo callee) {}
+]]></programlisting>
<para>is equivalent to...</para>
<programlisting><![CDATA[
- pointcut anyCall(int i, Foo callee) : call(* *.*(int)) && args(i) && target(callee);
- ]]></programlisting>
+pointcut anyCall(int i, Foo callee) : call(* *.*(int)) && args(i) && target(callee);
+]]></programlisting>
<para>An example with modifiers (Remember that Java 5 annotations are not
inherited, so the <literal>@Pointcut</literal> annotation must be
present on the extending aspect's pointcut declaration too):</para>
<programlisting><![CDATA[
- @Pointcut("")
- protected abstract void anyCall();
- ]]></programlisting>
+@Pointcut("")
+protected abstract void anyCall();
+]]></programlisting>
<para>is equivalent to...</para>
<programlisting><![CDATA[
- protected abstract pointcut anyCall();
- ]]></programlisting>
+protected abstract pointcut anyCall();
+]]></programlisting>
<sect3>
<title>Type references inside @AspectJ annotations</title>
@@ -196,39 +196,34 @@
</para>
<programlisting><![CDATA[
- package org.aspectprogrammer.examples;
+package org.aspectprogrammer.examples;
- import java.util.List;
+import java.util.List;
- public aspect Foo {
-
- pointcut listOperation() : call(* List.*(..));
-
- pointcut anyUtilityCall() : call(* java.util..*(..));
-
- }
- ]]></programlisting>
+public aspect Foo {
+ pointcut listOperation() : call(* List.*(..));
+ pointcut anyUtilityCall() : call(* java.util..*(..));
+}
+]]></programlisting>
<para>
Using the annotation style this would be written as:
</para>
<programlisting><![CDATA[
- package org.aspectprogrammer.examples;
-
- import java.util.List; // redundant but harmless
+package org.aspectprogrammer.examples;
- @Aspect
- public class Foo {
+import java.util.List; // redundant but harmless
- @Pointcut("call(* java.util.List.*(..))") // must qualify
- void listOperation() {}
+@Aspect
+public class Foo {
+ @Pointcut("call(* java.util.List.*(..))") // must qualify
+ void listOperation() {}
- @Pointcut("call(* java.util..*(..))")
- void anyUtilityCall() {}
-
- }
- ]]></programlisting>
+ @Pointcut("call(* java.util..*(..))")
+ void anyUtilityCall() {}
+}
+]]></programlisting>
</sect3>
@@ -267,45 +262,45 @@
</para>
<programlisting><![CDATA[
- @Pointcut("call(* *.*(int)) && args(i) && if()")
- public static boolean someCallWithIfTest(int i) {
- return i > 0;
- }
- ]]></programlisting>
+@Pointcut("call(* *.*(int)) && args(i) && if()")
+public static boolean someCallWithIfTest(int i) {
+ return i > 0;
+}
+]]></programlisting>
<para>is equivalent to...</para>
<programlisting><![CDATA[
- pointcut someCallWithIfTest(int i) : call(* *.*(int)) && args(i) && if(i > 0);
- ]]></programlisting>
+pointcut someCallWithIfTest(int i) : call(* *.*(int)) && args(i) && if(i > 0);
+]]></programlisting>
<para>and the following is also a valid form:</para>
<programlisting><![CDATA[
- static int COUNT = 0;
-
- @Pointcut("call(* *.*(int)) && args(i) && if()")
- public static boolean someCallWithIfTest(int i, JoinPoint jp, JoinPoint.EnclosingStaticPart esjp) {
- // any legal Java expression...
- return i > 0
- && jp.getSignature().getName.startsWith("doo")
- && esjp.getSignature().getName().startsWith("test")
- && COUNT++ < 10;
- }
-
- @Before("someCallWithIfTest(anInt, jp, enc)")
- public void beforeAdviceWithRuntimeTest(int anInt, JoinPoint jp, JoinPoint.EnclosingStaticPart enc) {
- //...
- }
-
- // Note that the following is NOT valid
- /*
- @Before("call(* *.*(int)) && args(i) && if()")
- public void advice(int i) {
- // so you were writing an advice or an if body ?
- }
- */
- ]]></programlisting>
+static int COUNT = 0;
+
+@Pointcut("call(* *.*(int)) && args(i) && if()")
+public static boolean someCallWithIfTest(int i, JoinPoint jp, JoinPoint.EnclosingStaticPart esjp) {
+ // any legal Java expression...
+ return i > 0
+ && jp.getSignature().getName.startsWith("doo")
+ && esjp.getSignature().getName().startsWith("test")
+ && COUNT++ < 10;
+}
+
+@Before("someCallWithIfTest(anInt, jp, enc)")
+public void beforeAdviceWithRuntimeTest(int anInt, JoinPoint jp, JoinPoint.EnclosingStaticPart enc) {
+ //...
+}
+
+// Note that the following is NOT valid
+/*
+@Before("call(* *.*(int)) && args(i) && if()")
+public void advice(int i) {
+ // so you were writing an advice or an if body ?
+}
+*/
+]]></programlisting>
<para>
It is thus possible with the annotation style to use the
@@ -377,19 +372,19 @@
both styles:</para>
<programlisting><![CDATA[
- @Before("call(* org.aspectprogrammer..*(..)) && this(Foo)")
- public void callFromFoo() {
- System.out.println("Call from Foo");
- }
- ]]></programlisting>
+@Before("call(* org.aspectprogrammer..*(..)) && this(Foo)")
+public void callFromFoo() {
+ System.out.println("Call from Foo");
+}
+]]></programlisting>
<para>is equivalent to...</para>
<programlisting><![CDATA[
- before() : call(* org.aspectprogrammer..*(..)) && this(Foo) {
- System.out.println("Call from Foo");
- }
- ]]></programlisting>
+before() : call(* org.aspectprogrammer..*(..)) && this(Foo) {
+ System.out.println("Call from Foo");
+}
+]]></programlisting>
<!--
@@ -405,19 +400,18 @@
</para>
<programlisting><![CDATA[
- @AdviceName("callFromFoo")
- before() : call(* org.aspectprogrammer..*(..)) && this(Foo) {
- System.out.println("Call from Foo");
- }
-
- is equivalent to...
-
- @Before("call(* org.aspectprogrammer..*(..)) && this(Foo)")
- public void callFromFoo() {
- System.out.println("Call from Foo");
- }
- ]]></programlisting>
-
+@AdviceName("callFromFoo")
+before() : call(* org.aspectprogrammer..*(..)) && this(Foo) {
+ System.out.println("Call from Foo");
+}
+
+is equivalent to...
+
+@Before("call(* org.aspectprogrammer..*(..)) && this(Foo)")
+public void callFromFoo() {
+ System.out.println("Call from Foo");
+}
+]]></programlisting>
-->
<para>If the advice body needs to know which particular
@@ -427,19 +421,19 @@
</para>
<programlisting><![CDATA[
- before(Foo foo) : call(* org.aspectprogrammer..*(..)) && this(foo) {
- System.out.println("Call from Foo: " + foo);
- }
- ]]></programlisting>
+before(Foo foo) : call(* org.aspectprogrammer..*(..)) && this(foo) {
+ System.out.println("Call from Foo: " + foo);
+}
+]]></programlisting>
<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);
- }
- ]]></programlisting>
+@Before("call(* org.aspectprogrammer..*(..)) && this(foo)")
+public void callFromFoo(Foo foo) {
+ System.out.println("Call from Foo: " + foo);
+}
+]]></programlisting>
<para>If the advice body needs access to
<literal>thisJoinPoint</literal>
@@ -453,32 +447,32 @@
</para>
<programlisting><![CDATA[
- @Before("call(* org.aspectprogrammer..*(..)) && this(foo)")
- public void callFromFoo(JoinPoint thisJoinPoint, Foo foo) {
- System.out.println("Call from Foo: " + foo + " at "
- + thisJoinPoint);
- }
- ]]></programlisting>
+@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>
+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[
- @Before("call(* org.aspectprogrammer..*(..)) && this(Foo)")
- public void callFromFoo(JoinPoint thisJoinPoint,
- JoinPoint.StaticPart thisJoinPointStaticPart,
- JoinPoint.EnclosingStaticPart thisEnclosingJoinPointStaticPart) {
- // ...
- }
- ]]></programlisting>
+@Before("call(* org.aspectprogrammer..*(..)) && this(Foo)")
+public void callFromFoo(JoinPoint thisJoinPoint,
+ JoinPoint.StaticPart thisJoinPointStaticPart,
+ JoinPoint.EnclosingStaticPart thisEnclosingJoinPointStaticPart) {
+ // ...
+}
+]]></programlisting>
<para>
<literal>JoinPoint.EnclosingStaticPart</literal>
@@ -514,28 +508,28 @@
</para>
<programlisting><![CDATA[
- @AfterReturning("criticalOperation()")
- public void phew() {
- System.out.println("phew");
- }
+@AfterReturning("criticalOperation()")
+public void phew() {
+ System.out.println("phew");
+}
- @AfterReturning(pointcut="call(Foo+.new(..))",returning="f")
- public void itsAFoo(Foo f) {
- System.out.println("It's a Foo: " + f);
- }
- ]]></programlisting>
+@AfterReturning(pointcut="call(Foo+.new(..))",returning="f")
+public void itsAFoo(Foo f) {
+ System.out.println("It's a Foo: " + f);
+}
+]]></programlisting>
<para>is equivalent to...</para>
<programlisting><![CDATA[
- after() returning : criticalOperation() {
- System.out.println("phew");
- }
+after() returning : criticalOperation() {
+ System.out.println("phew");
+}
- after() returning(Foo f) : call(Foo+.new(..)) {
- System.out.println("It's a Foo: " + f);
- }
- ]]></programlisting>
+after() returning(Foo f) : call(Foo+.new(..)) {
+ System.out.println("It's a Foo: " + f);
+}
+]]></programlisting>
<para>(Note the use of the "pointcut=" prefix in front of the pointcut
expression in the returning case).</para>
@@ -557,11 +551,11 @@
</para>
<programlisting><![CDATA[
- @Around("call(* org.aspectprogrammer..*(..))")
- public Object doNothing() {
- return proceed(); // CE on this line
- }
- ]]></programlisting>
+@Around("call(* org.aspectprogrammer..*(..))")
+public Object doNothing() {
+ return proceed(); // CE on this line
+}
+]]></programlisting>
<para>will result in a "No such method" compilation error. For this
@@ -573,50 +567,48 @@
</para>
<programlisting><![CDATA[
- public interface ProceedingJoinPoint extends JoinPoint {
- public Object proceed(Object[] args);
- }
- ]]></programlisting>
+public interface ProceedingJoinPoint extends JoinPoint {
+ public Object proceed(Object[] args);
+}
+]]></programlisting>
<para>The around advice given above can now be written as:</para>
<programlisting><![CDATA[
- @Around("call(* org.aspectprogrammer..*(..))")
- public Object doNothing(ProceedingJoinPoint thisJoinPoint) {
- return thisJoinPoint.proceed();
- }
- ]]></programlisting>
+@Around("call(* org.aspectprogrammer..*(..))")
+public Object doNothing(ProceedingJoinPoint thisJoinPoint) {
+ return thisJoinPoint.proceed();
+}
+]]></programlisting>
<para>Here's an example that uses parameters for the proceed call:</para>
<programlisting><![CDATA[
- @Aspect
- public class ProceedAspect {
-
- @Pointcut("call(* setAge(..)) && args(i)")
- void setAge(int i) {}
+@Aspect
+public class ProceedAspect {
- @Around("setAge(i)")
- public Object twiceAsOld(ProceedingJoinPoint thisJoinPoint, int i) {
- return thisJoinPoint.proceed(new Object[]{i*2}); //using Java 5 autoboxing
- }
+ @Pointcut("call(* setAge(..)) && args(i)")
+ void setAge(int i) {}
- }
+ @Around("setAge(i)")
+ public Object twiceAsOld(ProceedingJoinPoint thisJoinPoint, int i) {
+ return thisJoinPoint.proceed(new Object[]{i*2}); //using Java 5 autoboxing
+ }
- ]]></programlisting>
+}
+]]></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>
+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>
@@ -626,15 +618,15 @@
<itemizedlist>
<listitem>If 'this()' was used in the pointcut <emphasis>for binding</emphasis>, it must be passed first in proceed(..).
</listitem>
- <listitem>If 'target()' was used in the pointcut <emphasis>for binding</emphasis>, it must be passed next in proceed(..) - it will be the
+ <listitem>If 'target()' was used in the pointcut <emphasis>for binding</emphasis>, it must be passed next in proceed(..) - it will be the
first argument to proceed(..) if this() was not used for binding.
</listitem>
- <listitem>Finally come <emphasis>all</emphasis> the arguments expected at the join point, in the order they
- are supplied at the join point. Effectively the advice signature is ignored - it doesn't
- matter if a subset of arguments were bound or the ordering was changed in the advice
+ <listitem>Finally come <emphasis>all</emphasis> the arguments expected at the join point, in the order they
+ are supplied at the join point. Effectively the advice signature is ignored - it doesn't
+ matter if a subset of arguments were bound or the ordering was changed in the advice
signature, the proceed(..) calls takes all of them in the right order for the join point.
</listitem>
- </itemizedlist>
+ </itemizedlist>
</para>
<para>Since proceed(..) in this case takes an Object array, AspectJ cannot do as much compile time
checking as it can for code style. If the rules above aren't obeyed then it will unfortunately
@@ -650,11 +642,11 @@
<para>
Inter-type declarations are challenging to support using an annotation style. For code style aspects
compiled with the ajc compiler, the entire type system can be made aware of inter-type declarations (new
- supertypes, new methods, new fields) and the completeness and correctness of it can be guaranteed.
+ supertypes, new methods, new fields) and the completeness and correctness of it can be guaranteed.
Achieving this with an annotation style is hard because the source code may simply be compiled with javac
where the type system cannot be influenced and what is compiled must be 'pure java'.
</para>
- <para>
+ <para>
AspectJ 1.5.0 introduced @DeclareParents, an attempt to offer something like that which is achievable with
code style declare parents and the other intertype declarations (fields, methods, constructors). However,
it has proved too challenging to get close to the expressiveness and capabilities of code style in this area
@@ -662,12 +654,12 @@
some interface I is mixed into some target type T then this means that all the methods from I are created in T and their
implementations are simple forwarding methods that call a delegate which that provides an implementation of I.
</para>
- <para>
- The next section covers @DeclareParents but AspectJ 1.6.4 introduces @DeclareMixin - an improved approach to defining
- a mixin and the choice of a different name for the annotation will hopefully alleviate some of the confusion about
- why @DeclareParents just doesn't offer the same semantics as the code style variant. Offering @DeclareMixin also gives
- code style developers a new tool for a simple mixin whereas previously they would have avoided @DeclareParents
- thinking what it could only do was already achievable with code style syntax.
+ <para>
+ The next section covers @DeclareParents but AspectJ 1.6.4 introduces @DeclareMixin - an improved approach to defining
+ a mixin and the choice of a different name for the annotation will hopefully alleviate some of the confusion about
+ why @DeclareParents just doesn't offer the same semantics as the code style variant. Offering @DeclareMixin also gives
+ code style developers a new tool for a simple mixin whereas previously they would have avoided @DeclareParents
+ thinking what it could only do was already achievable with code style syntax.
</para>
<para>
The defaultImpl attribute of @DeclareParents may become deprecated if @DeclareMixin proves popular, leaving
@@ -683,23 +675,23 @@
</para>
<programlisting><![CDATA[
- public aspect MoodIndicator {
+public aspect MoodIndicator {
- public interface Moody {};
+ public interface Moody {};
- private Mood Moody.mood = Mood.HAPPY;
+ private Mood Moody.mood = Mood.HAPPY;
- public Mood Moody.getMood() {
- return mood;
- }
+ public Mood Moody.getMood() {
+ return mood;
+ }
- declare parents : org.xyz..* implements Moody;
+ declare parents : org.xyz..* implements Moody;
- before(Moody m) : execution(* *.*(..)) && this(m) {
- System.out.println("I'm feeling " + m.getMood());
- }
- }
- ]]></programlisting>
+ before(Moody m) : execution(* *.*(..)) && this(m) {
+ System.out.println("I'm feeling " + m.getMood());
+ }
+}
+]]></programlisting>
<para>
This declares an interface
@@ -720,33 +712,33 @@
</para>
<programlisting><![CDATA[
- @Aspect
- public class MoodIndicator {
-
- // this interface can be outside of the aspect
- public interface Moody {
- Mood getMood();
- };
-
- // this implementation can be outside of the aspect
- public static class MoodyImpl implements Moody {
- private Mood mood = Mood.HAPPY;
-
- public Mood getMood() {
- return mood;
- }
- }
-
- // the field type must be the introduced interface. It can't be a class.
- @DeclareParents(value="org.xzy..*",defaultImpl=MoodyImpl.class)
- private Moody implementedInterface;
-
- @Before("execution(* *.*(..)) && this(m)")
- void feelingMoody(Moody m) {
- System.out.println("I'm feeling " + m.getMood());
- }
- }
- ]]></programlisting>
+@Aspect
+public class MoodIndicator {
+
+ // this interface can be outside of the aspect
+ public interface Moody {
+ Mood getMood();
+ };
+
+ // this implementation can be outside of the aspect
+ public static class MoodyImpl implements Moody {
+ private Mood mood = Mood.HAPPY;
+
+ public Mood getMood() {
+ return mood;
+ }
+ }
+
+ // the field type must be the introduced interface. It can't be a class.
+ @DeclareParents(value="org.xzy..*",defaultImpl=MoodyImpl.class)
+ private Moody implementedInterface;
+
+ @Before("execution(* *.*(..)) && this(m)")
+ void feelingMoody(Moody m) {
+ System.out.println("I'm feeling " + m.getMood());
+ }
+}
+]]></programlisting>
<para>
This is very similar to the mixin mechanism supported by AspectWerkz. The
@@ -762,7 +754,7 @@
has access
to the exact same set of members as in the code style example.
</para>
-
+
<para>
Note that it is illegal to use the @DeclareParents annotation on an aspect' field of a non-interface type.
The interface type is the inter-type declaration contract that dictates
@@ -770,21 +762,21 @@
</para>
<programlisting><![CDATA[
- // this type will be affected by the inter-type declaration as the type pattern matches
- package org.xyz;
- public class MoodTest {
-
- public void test() {
- // see here the cast to the introduced interface (required)
- Mood mood = ((Moody)this).getMood();
- ...
- }
- }
- ]]></programlisting>
+// this type will be affected by the inter-type declaration as the type pattern matches
+package org.xyz;
+public class MoodTest {
+
+ public void test() {
+ // see here the cast to the introduced interface (required)
+ Mood mood = ((Moody)this).getMood();
+ ...
+ }
+}
+]]></programlisting>
<para>The <literal>@DeclareParents</literal> annotation can also be used without specifying
- a <literal>defaultImpl</literal> value (for example,
- <literal>@DeclareParents("org.xyz..*")</literal>). This is equivalent to a
+ a <literal>defaultImpl</literal> value (for example,
+ <literal>@DeclareParents("org.xyz..*")</literal>). This is equivalent to a
<literal>declare parents ... implements</literal> clause, and does <emphasis>not</emphasis>
make any inter-type declarations for default implementation of the interface methods.
</para>
@@ -794,32 +786,30 @@
</para>
<programlisting><![CDATA[
- public aspect SerializableMarker {
-
- declare parents : org.xyz..* implements Serializable;
- }
- ]]></programlisting>
+public aspect SerializableMarker {
+ declare parents : org.xyz..* implements Serializable;
+}
+]]></programlisting>
<para>Using the annotation style this aspect can be written:
</para>
<programlisting><![CDATA[
- @Aspect
- public class SerializableMarker {
-
- @DeclareParents("org.xyz..*")
- Serializable implementedInterface;
- }
- ]]></programlisting>
+@Aspect
+public class SerializableMarker {
+ @DeclareParents("org.xyz..*")
+ Serializable implementedInterface;
+}
+]]></programlisting>
<para>
If the interface defines one or more operations, and these are not implemented by
the target type, an error will be issued during weaving.
</para>
-
+
</sect2>
-
+
<sect2 id="atDeclareMixin" xreflabel="atDeclareMixin">
<title>@DeclareMixin</title>
<para>
@@ -827,26 +817,26 @@
</para>
<programlisting><![CDATA[
- public aspect MoodIndicator {
+public aspect MoodIndicator {
- public interface Moody {};
+ public interface Moody {};
- private Mood Moody.mood = Mood.HAPPY;
+ private Mood Moody.mood = Mood.HAPPY;
- public Mood Moody.getMood() {
- return mood;
- }
+ public Mood Moody.getMood() {
+ return mood;
+ }
- declare parents : org.xyz..* implements Moody;
+ declare parents : org.xyz..* implements Moody;
- before(Moody m) : execution(* *.*(..)) && this(m) {
- System.out.println("I'm feeling " + m.getMood());
- }
- }
- ]]></programlisting>
+ before(Moody m) : execution(* *.*(..)) && this(m) {
+ System.out.println("I'm feeling " + m.getMood());
+ }
+}
+]]></programlisting>
<para>
- This declares an interface <literal>Moody</literal>, and then makes two inter-type declarations on the interface
+ This declares an interface <literal>Moody</literal>, and then makes two inter-type declarations on the interface
- a field that is private to the aspect, and a method that returns the mood. Within the body of the inter-type
declared method <literal>getMoody</literal>, the type of <literal>this</literal> is <literal>Moody</literal>
(the target type of the inter-type declaration).
@@ -856,37 +846,37 @@
</para>
<programlisting><![CDATA[
- @Aspect
- public class MoodIndicator {
-
- // this interface can be outside of the aspect
- public interface Moody {
- Mood getMood();
- };
-
- // this implementation can be outside of the aspect
- public static class MoodyImpl implements Moody {
- private Mood mood = Mood.HAPPY;
-
- public Mood getMood() {
- return mood;
- }
- }
-
- // The DeclareMixin annotation is attached to a factory method that can return instances of the delegate
- // which offers an implementation of the mixin interface. The interface that is mixed in is the
- // return type of the method.
- @DeclareMixin("org.xyz..*")
- public static Moody createMoodyImplementation() {
- return new MoodyImpl();
- }
-
- @Before("execution(* *.*(..)) && this(m)")
- void feelingMoody(Moody m) {
- System.out.println("I'm feeling " + m.getMood());
- }
- }
- ]]></programlisting>
+@Aspect
+public class MoodIndicator {
+
+ // this interface can be outside of the aspect
+ public interface Moody {
+ Mood getMood();
+ };
+
+ // this implementation can be outside of the aspect
+ public static class MoodyImpl implements Moody {
+ private Mood mood = Mood.HAPPY;
+
+ public Mood getMood() {
+ return mood;
+ }
+ }
+
+ // The DeclareMixin annotation is attached to a factory method that can return instances of the delegate
+ // which offers an implementation of the mixin interface. The interface that is mixed in is the
+ // return type of the method.
+ @DeclareMixin("org.xyz..*")
+ public static Moody createMoodyImplementation() {
+ return new MoodyImpl();
+ }
+
+ @Before("execution(* *.*(..)) && this(m)")
+ void feelingMoody(Moody m) {
+ System.out.println("I'm feeling " + m.getMood());
+ }
+}
+]]></programlisting>
<para>
Basically, the <literal>@DeclareMixin</literal> annotation is attached to a factory method. The
@@ -894,24 +884,24 @@
create an instance of a delegate that implements the interface. This is the interface which will
be delegated to from any target matching the specified type pattern.
</para>
-
+
<para>
Exploiting this syntax requires the user to obey the rules of pure Java. So references to any
targeted type as if it were affected by the Mixin must be made through a cast, like this:
</para>
-
+
<programlisting><![CDATA[
- // this type will be affected by the inter-type declaration as the type pattern matches
- package org.xyz;
- public class MoodTest {
-
- public void test() {
- // see here the cast to the introduced interface (required)
- Mood mood = ((Moody)this).getMood();
- ...
- }
- }
- ]]></programlisting>
+// this type will be affected by the inter-type declaration as the type pattern matches
+package org.xyz;
+public class MoodTest {
+
+ public void test() {
+ // see here the cast to the introduced interface (required)
+ Mood mood = ((Moody)this).getMood();
+ ...
+ }
+}
+]]></programlisting>
<para>
Sometimes the delegate instance may want to perform differently depending upon the type/instance for
@@ -920,54 +910,52 @@
which a delegate should be created:
</para>
<programlisting><![CDATA[
-
- @Aspect
- public class Foo {
-
- @DeclareMixin("org.xyz..*")
- public static SomeInterface createDelegate(Object instance) {
- return new SomeImplementation(instance);
- }
- }
- ]]></programlisting>
-
+@Aspect
+public class Foo {
+
+ @DeclareMixin("org.xyz..*")
+ public static SomeInterface createDelegate(Object instance) {
+ return new SomeImplementation(instance);
+ }
+}
+]]></programlisting>
+
<para>
- It is also possible to make the factory method non-static - and in this case it can then exploit
+ It is also possible to make the factory method non-static - and in this case it can then exploit
the local state in the surrounding aspect instance, but this is only supported for singleton aspects:
</para>
<programlisting><![CDATA[
-
- @Aspect
- public class Foo {
- public int maxLimit=35;
-
- @DeclareMixin("org.xyz..*")
- public SomeInterface createDelegate(Object instance) {
- return new SomeImplementation(instance,maxLimit);
- }
- }
- ]]></programlisting>
-
+@Aspect
+public class Foo {
+ public int maxLimit=35;
+
+ @DeclareMixin("org.xyz..*")
+ public SomeInterface createDelegate(Object instance) {
+ return new SomeImplementation(instance,maxLimit);
+ }
+}
+]]></programlisting>
+
<para>
Although the interface type is usually determined purely from the return type of the factory method, it can
be specified in the annotation if necessary. In this example the return type of the method extends multiple
other interfaces and only a couple of them (I and J) should be mixed into any matching targets:
</para>
<programlisting><![CDATA[
- // interfaces is an array of interface classes that should be mixed in
- @DeclareMixin(value="org.xyz..*",interfaces={I.class,J.class})
- public static InterfaceExtendingLotsOfInterfaces createMoodyImplementation() {
- return new MoodyImpl();
- }
- ]]></programlisting>
-
+// interfaces is an array of interface classes that should be mixed in
+@DeclareMixin(value="org.xyz..*",interfaces={I.class,J.class})
+public static InterfaceExtendingLotsOfInterfaces createMoodyImplementation() {
+ return new MoodyImpl();
+}
+]]></programlisting>
+
<para>
There are clearly similarities between <literal>@DeclareMixin</literal> and <literal>@DeclareParents</literal> but
<literal>@DeclareMixin</literal> is not pretending to offer more than a simple mixin strategy. The flexibility in
- being able to provide the factory method instead of requiring a no-arg constructor for the implementation also
+ being able to provide the factory method instead of requiring a no-arg constructor for the implementation also
enables delegate instances to make decisions based upon the type for which they are the delegate.
</para>
-
+
<para>
Any annotations defined on the interface methods are also put upon the delegate forwarding methods created in the
matched target type.
@@ -997,21 +985,24 @@
</para>
<programlisting><![CDATA[
- public aspect SystemArchitecture {
- declare precedence : Security*, TransactionSupport, Persistence;
+public aspect SystemArchitecture {
+ declare precedence : Security*, TransactionSupport, Persistence;
- // ...
- }
+ // ...
+}
+]]></programlisting>
- can be written as:
-
- @Aspect
- @DeclarePrecedence("Security*,org.xyz.TransactionSupport,org.xyz.Persistence")
- public class SystemArchitecture {
+ <para>
+ can be written as:
+ </para>
- // ...
- }
- ]]></programlisting>
+ <programlisting><![CDATA[
+@Aspect
+@DeclarePrecedence("Security*,org.xyz.TransactionSupport,org.xyz.Persistence")
+public class SystemArchitecture {
+ // ...
+}
+]]></programlisting>
<!--
note: below is not supported for now.
@@ -1026,32 +1017,34 @@
</para>
<programlisting><![CDATA[
- public aspect DeclareAnnotationExamples {
- declare annotation : org.xyz.model..* : @BusinessDomain;
+public aspect DeclareAnnotationExamples {
+ declare annotation : org.xyz.model..* : @BusinessDomain;
- declare annotation : public * BankAccount+.*(..) : @Secured(role="supervisor");
+ declare annotation : public * BankAccount+.*(..) : @Secured(role="supervisor");
- declare anotation : * DAO+.* : @Persisted;
+ declare anotation : * DAO+.* : @Persisted;
- }
+}
+]]></programlisting>
- can be written as...
+ <para>can be written as...</para>
- @Aspect
- public class DeclareAnnotationExamples {
+ <programlisting><![CDATA[
+@Aspect
+public class DeclareAnnotationExamples {
- @DeclareAnnotation("org.xyz.model..*)
- @BusinessDomain Object modelClass;
+ @DeclareAnnotation("org.xyz.model..*)
+ @BusinessDomain Object modelClass;
- // this example assumes that the @Secured annotation has a Target
- // annotation with value ElementType.METHOD
- @DeclareAnnotation("public * org.xyz.banking.BankAccount+.*(..)")
- @Secured(role="supervisor) void bankAccountMethod();
+ // this example assumes that the @Secured annotation has a Target
+ // annotation with value ElementType.METHOD
+ @DeclareAnnotation("public * org.xyz.banking.BankAccount+.*(..)")
+ @Secured(role="supervisor) void bankAccountMethod();
- @DeclareAnnotation("* DAO+.*")
- @Persisted Object daoFields;
- }
- ]]></programlisting>
+ @DeclareAnnotation("* DAO+.*")
+ @Persisted Object daoFields;
+}
+]]></programlisting>
<para>
<emphasis>Note: Declare annotation is not available in AspectJ 1.5 M3 and syntax may change
@@ -1069,29 +1062,29 @@
of a static method for example.</para>
<programlisting><![CDATA[
- declare warning : call(* javax.sql..*(..)) && !within(org.xyz.daos..*)
- : "Only DAOs should be calling JDBC.";
-
- declare error : execution(* IFoo+.*(..)) && !within(org.foo..*)
- : "Only foo types can implement IFoo";
+declare warning : call(* javax.sql..*(..)) && !within(org.xyz.daos..*)
+ : "Only DAOs should be calling JDBC.";
- can be written as...
+declare error : execution(* IFoo+.*(..)) && !within(org.foo..*)
+ : "Only foo types can implement IFoo";
+]]></programlisting>
- @DeclareWarning("call(* javax.sql..*(..)) && !within(org.xyz.daos..*)")
- static final String aMessage = "Only DAOs should be calling JDBC.";
+ <para>can be written as...</para>
- @DeclareError("execution(* IFoo+.*(..)) && !within(org.foo..*)")
- static final String badIFooImplementors = "Only foo types can implement IFoo";
-
- // the following is not valid since the message is not a String literal
- @DeclareError("execution(* IFoo+.*(..)) && !within(org.foo..*)")
- static final String badIFooImplementorsCorrupted = getMessage();
- static String getMessage() {
- return "Only foo types can implement IFoo " + System.currentTimeMillis();
- }
+ <programlisting><![CDATA[
+@DeclareWarning("call(* javax.sql..*(..)) && !within(org.xyz.daos..*)")
+static final String aMessage = "Only DAOs should be calling JDBC.";
- ]]></programlisting>
+@DeclareError("execution(* IFoo+.*(..)) && !within(org.foo..*)")
+static final String badIFooImplementors = "Only foo types can implement IFoo";
+// the following is not valid since the message is not a String literal
+@DeclareError("execution(* IFoo+.*(..)) && !within(org.foo..*)")
+static final String badIFooImplementorsCorrupted = getMessage();
+static String getMessage() {
+ return "Only foo types can implement IFoo " + System.currentTimeMillis();
+}
+]]></programlisting>
</sect1>
@@ -1117,27 +1110,27 @@
</para>
<programlisting><![CDATA[
- public class Aspects {
+public class Aspects {
- /* variation used for singleton, percflow, percflowbelow */
- static<T> public static T aspectOf(T aspectType) {...}
+ /* variation used for singleton, percflow, percflowbelow */
+ static<T> public static T aspectOf(T aspectType) {...}
- /* variation used for perthis, pertarget */
- static<T> public static T aspectOf(T aspectType, Object forObject) {...}
+ /* variation used for perthis, pertarget */
+ static<T> public static T aspectOf(T aspectType, Object forObject) {...}
- /* variation used for pertypewithin */
- static<T> public static T aspectOf(T aspectType, Class forType) {...}
+ /* variation used for pertypewithin */
+ static<T> public static T aspectOf(T aspectType, Class forType) {...}
- /* variation used for singleton, percflow, percflowbelow */
- public static boolean hasAspect(Object anAspect) {...}
+ /* variation used for singleton, percflow, percflowbelow */
+ public static boolean hasAspect(Object anAspect) {...}
- /* variation used for perthis, pertarget */
- public static boolean hasAspect(Object anAspect, Object forObject) {...}
+ /* variation used for perthis, pertarget */
+ public static boolean hasAspect(Object anAspect, Object forObject) {...}
- /* variation used for pertypewithin */
- public static boolean hasAspect(Object anAspect, Class forType) {...}
- }
- ]]></programlisting>
+ /* variation used for pertypewithin */
+ public static boolean hasAspect(Object anAspect, Class forType) {...}
+}
+]]></programlisting>
<!-- TODO AV - stuff below is not done -->
<!--