<title>Introduction</title>
<para>In addition to the familiar AspectJ code-based style of aspect
- declaration, AspectJ 5 also supports an annotation-based style of
- aspect declaration. We informally call the set of annotations that
- support this development style the "@AspectJ" annotations.</para>
+ declaration, AspectJ 5 also supports an annotation-based style of
+ aspect declaration. We informally call the set of annotations that
+ support this development style the "@AspectJ" annotations.</para>
<para>
- AspectJ 5 allows aspects and their members to be specified using
- either the code style or the annotation style. Whichever style you
- use, the AspectJ weaver ensures that your program has exactly the
- same semantics. It is, to quote a famous advertising campaign,
- "a choice, not a compromise". The two styles can be mixed within
- a single application, and even within a single source file, though
- we doubt this latter mix will be recommended in practice.
+ AspectJ 5 allows aspects and their members to be specified using
+ either the code style or the annotation style. Whichever style you
+ use, the AspectJ weaver ensures that your program has exactly the
+ same semantics. It is, to quote a famous advertising campaign,
+ "a choice, not a compromise". The two styles can be mixed within
+ a single application, and even within a single source file, though
+ we doubt this latter mix will be recommended in practice.
</para>
<para>
- The use of the @AspectJ annotations means that there are large
- classes of AspectJ applications that can be compiled by a regular
- Java 5 compiler, and subsequently woven by the AspectJ weaver (for
- example, as an additional build stage, or as late as class load-time).
- In this chapter we introduce the @AspectJ annotations and show how
- they can be used to declare aspects and aspect members.
+ The use of the @AspectJ annotations means that there are large
+ classes of AspectJ applications that can be compiled by a regular
+ Java 5 compiler, and subsequently woven by the AspectJ weaver (for
+ example, as an additional build stage, or as late as class load-time).
+ In this chapter we introduce the @AspectJ annotations and show how
+ they can be used to declare aspects and aspect members.
</para>
</sect1>
<title>Aspect Declarations</title>
<para>
- Aspect declarations are supported by the
- <literal>org.aspectj.lang.annotation.Aspect</literal> annotation.
- The declaration:
+ Aspect declarations are supported by the
+ <literal>org.aspectj.lang.annotation.Aspect</literal>
+ annotation.
+ The declaration:
</para>
<programlisting><![CDATA[
]]></programlisting>
<para>To specify an aspect an aspect instantiation model (the default is
- singleton), provide the perclause as the
- <literal>@Aspect</literal> value.
- For example:
+ singleton), provide the perclause as the
+ <literal>@Aspect</literal>
+ value.
+ For example:
</para>
<programlisting><![CDATA[
public class Foo {}
]]></programlisting>
- <para>is equivalent to...</para>
+ <para>is equivalent to...</para>
<programlisting><![CDATA[
public aspect Foo perthis(execution(* abc..*(..))) {}
]]></programlisting>
- <sect2 id="limitations" xreflabel="limitations">
- <title>Limitations</title>
-
- <para>Privileged aspects are not supported by the annotation style.</para>
- <!--
- <programlisting><![CDATA[
- @Aspect(isPrivileged=true)
- public class Foo {}
- ]]></programlisting>
+ <sect2 id="limitations" xreflabel="limitations">
+ <title>Limitations</title>
- <para>is equivalent to...</para>
+ <para>Privileged aspects are not supported by the annotation style.</para>
+ <!--
+ <programlisting><![CDATA[
+ @Aspect(isPrivileged=true)
+ public class Foo {}
+ ]]></programlisting>
- <programlisting><![CDATA[
- public privileged aspect Foo {}
- ]]></programlisting>
- -->
- </sect2>
+ <para>is equivalent to...</para>
+
+ <programlisting><![CDATA[
+ public privileged aspect Foo {}
+ ]]></programlisting>
+ -->
+ </sect2>
</sect1>
<title>Pointcuts and Advice</title>
<para>
- Pointcut and advice declarations can be made using the
+ Pointcut and advice declarations can be made using the
<literal>Pointcut, Before, After, AfterReturning, AfterThrowing,</literal>
- and
- <literal>Around</literal> annotations.
+ and
+ <literal>Around</literal>
+ annotations.
</para>
<sect2 id="pointcuts" xreflabel="pointcuts">
<title>Pointcuts</title>
<para>
- Pointcuts are specified using the
- <literal>org.aspectj.lang.annotation.Pointcut</literal> annotation
- on a method declaration. The method should have a
+ Pointcuts are specified using the
+ <literal>org.aspectj.lang.annotation.Pointcut</literal>
+ annotation
+ on a method declaration. The method should have a
<literal>void</literal>
- return type. The parameters of the method correspond to the parameters
- of the pointcut. The modifiers of the method correspond to the modifiers
- of the pointcut.
+ return type. The parameters of the method correspond to the parameters
+ of the pointcut. The modifiers of the method correspond to the modifiers
+ of the pointcut.
</para>
<para>
- As a general rule, the
- <literal>@Pointcut</literal> annotated method must have an empty method body
- and must not have any
- <literal>throws</literal> clause. If formal are bound (using
- <literal>args(), target(), this(), @args(), @target(), @this(), @annotation())</literal> in the
- pointcut, then they must appear in the method signature.
+ As a general rule, the
+ <literal>@Pointcut</literal>
+ annotated method must have an empty method body
+ and must not have any
+ <literal>throws</literal>
+ clause. If formal are bound (using
+ <literal>args(), target(), this(), @args(), @target(), @this(), @annotation())</literal>
+ in the
+ pointcut, then they must appear in the method signature.
</para>
<para>
- The <literal>if()</literal> pointcut is treated specially and is discussed in a later section.
+ The
+ <literal>if()</literal>
+ pointcut is treated specially and is discussed in a later section.
</para>
<para>Here is a simple example of a pointcut declaration in both code and @AspectJ styles:</para>
void anyCall() {}
]]></programlisting>
- <para>is equivalent to...</para>
+ <para>is equivalent to...</para>
- <programlisting><![CDATA[
+ <programlisting><![CDATA[
pointcut anyCall() : call(* *.*(..));
]]></programlisting>
void someCall(int i, Foo callee) {}
]]></programlisting>
- <para>is equivalent to...</para>
+ <para>is equivalent to...</para>
- <programlisting><![CDATA[
+ <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>
+ <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>
- <para>is equivalent to...</para>
+ <para>is equivalent to...</para>
- <programlisting><![CDATA[
+ <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.
- When using the annotation style, types referenced in pointcut
- expressions are resolved in the absence of any imports and so have
- 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
- does not apply to type patterns with wildcards, which are always resolved
- in a global scope.
- </para>
-
- <para>
- Consider the following compilation unit:
- </para>
-
- <programlisting><![CDATA[
+ <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.
+ When using the annotation style, types referenced in pointcut
+ expressions are resolved in the absence of any imports and so have
+ 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
+ does not apply to type patterns with wildcards, which are always resolved
+ in a global scope.
+ </para>
+
+ <para>
+ Consider the following compilation unit:
+ </para>
+
+ <programlisting><![CDATA[
package org.aspectprogrammer.examples;
import java.util.List;
}
]]></programlisting>
- <para>
- Using the annotation style this would be written as:
- </para>
+ <para>
+ Using the annotation style this would be written as:
+ </para>
- <programlisting><![CDATA[
+ <programlisting><![CDATA[
package org.aspectprogrammer.examples;
import java.util.List; // redundant but harmless
}
]]></programlisting>
- </sect3>
-
- <sect3>
- <title>if() pointcut expressions</title>
-
- <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>
-
- <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. 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[
+ </sect3>
+
+ <sect3>
+ <title>if() pointcut expressions</title>
+
+ <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>
+
+ <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. 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[
@Pointcut("call(* *.*(int)) && args(i) && if()")
public static boolean someCallWithIfTest(int i) {
return i > 0;
}
]]></programlisting>
- <para>is equivalent to...</para>
+ <para>is equivalent to...</para>
- <programlisting><![CDATA[
+ <programlisting><![CDATA[
pointcut someCallWithIfTest(int i) : call(* *.*(int)) && args(i) && if(i > 0);
]]></programlisting>
- <para> and the following is also a valid form:</para>
+ <para>and the following is also a valid form:</para>
- <programlisting><![CDATA[
+ <programlisting><![CDATA[
static int COUNT = 0;
@Pointcut("call(* *.*(int)) && args(i) && if()")
*/
]]></programlisting>
- <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 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> 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>
- The special forms <literal>if(true)</literal> and <literal>if(false)</literal> can be used in a more
- general way and don't imply that the pointcut method must have a body.
- You can thus write <literal>@Before("somePoincut() && if(false)")</literal>.
- </para>
-
- </sect3>
+ <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 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>
+ 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>
+ The special forms
+ <literal>if(true)</literal>
+ and
+ <literal>if(false)</literal>
+ can be used in a more
+ general way and don't imply that the pointcut method must have a body.
+ You can thus write
+ <literal>@Before("somePoincut() && if(false)")</literal>
+ .
+ </para>
+
+ </sect3>
</sect2>
<title>Advice</title>
<para>In this section we first discuss the use of annotations for
- simple advice declarations. Then we show how
+ simple advice declarations. Then we show how
<literal>thisJoinPoint</literal>
- and its siblings are handled in the body of advice and discuss the
- treatment of
- <literal>proceed</literal> in around advice.
+ and its siblings are handled in the body of advice and discuss the
+ treatment of
+ <literal>proceed</literal>
+ in around advice.
</para>
<para>Using the annotation style, an advice declaration is written as
- a regular Java method with one of the
+ a regular Java method with one of the
<literal>Before, After, AfterReturning,
- AfterThrowing,</literal> or
- <literal>Around</literal> annotations. Except in
- the case of around advice, the method should return void. The method should
- be declared public.
+ AfterThrowing,</literal>
+ or
+ <literal>Around</literal>
+ annotations. Except in
+ the case of around advice, the method should return void. The method should
+ be declared public.
</para>
<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).</para>
+ 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).</para>
<para>The following example shows a simple before advice declaration in
- both styles:</para>
+ both styles:</para>
- <programlisting><![CDATA[
+ <programlisting><![CDATA[
@Before("call(* org.aspectprogrammer..*(..)) && this(Foo)")
public void callFromFoo() {
System.out.println("Call from Foo");
}
]]></programlisting>
- <para>is equivalent to...</para>
+ <para>is equivalent to...</para>
<programlisting><![CDATA[
before() : call(* org.aspectprogrammer..*(..)) && this(Foo) {
]]></programlisting>
- <!--
- 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
- exact semantic equivalence between the two styles, we also support the
- <literal>org.aspectj.lang.annotation.AdviceName</literal> annotation.
- The exact equivalent declarations are:
- </para>
+ <!--
+ AMC: enhanced adviceexecution pointcuts and @AdviceName will most likely not make AJ5 1.5.0
- <programlisting><![CDATA[
- @AdviceName("callFromFoo")
- before() : call(* org.aspectprogrammer..*(..)) && this(Foo) {
- System.out.println("Call from Foo");
- }
+ <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
+ exact semantic equivalence between the two styles, we also support the
+ <literal>org.aspectj.lang.annotation.AdviceName</literal> annotation.
+ The exact equivalent declarations are:
+ </para>
- is equivalent to...
+ <programlisting><![CDATA[
+ @AdviceName("callFromFoo")
+ before() : call(* org.aspectprogrammer..*(..)) && this(Foo) {
+ System.out.println("Call from Foo");
+ }
- @Before("call(* org.aspectprogrammer..*(..)) && this(Foo)")
- public void callFromFoo() {
- System.out.println("Call from Foo");
- }
- ]]></programlisting>
-
- -->
+ 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
- <literal>Foo</literal> instance
- is making the call, 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[
}
]]></programlisting>
- <para>can be written as:</para>
+ <para>can be written as:</para>
<programlisting><![CDATA[
@Before("call(* org.aspectprogrammer..*(..)) && this(foo)")
]]></programlisting>
<para>If the advice body needs access to
- <literal>thisJoinPoint</literal>,
- <literal>thisJoinPointStaticPart</literal>,
- <literal>thisEnclosingJoinPointStaticPart</literal> then these need to
- be declared as additional method parameters when using the annotation
- style. <!-- TODO AV - not any more - In AspectJ 1.5.0 we require that these parameters be declared
- first in the parameter list, in later releases we may relax this
- requirement.-->
+ <literal>thisJoinPoint</literal>
+ ,
+ <literal>thisJoinPointStaticPart</literal>
+ ,
+ <literal>thisEnclosingJoinPointStaticPart</literal>
+ then these need to
+ be declared as additional method parameters when using the annotation
+ style.
</para>
<programlisting><![CDATA[
+ thisJoinPoint);
}
]]></programlisting>
-
- <para>is equivalent to...</para>
+
+ <para>is equivalent to...</para>
<programlisting><![CDATA[
before(Foo foo) : call(* org.aspectprogrammer..*(..)) && this(foo) {
+ thisJoinPoint);
}
]]></programlisting>
-
+
<para>Advice that needs all three variables would be declared:</para>
<programlisting><![CDATA[
]]></programlisting>
<para>
- <literal>JoinPoint.EnclosingStaticPart</literal> is a new (empty) sub-interface
- of
- <literal>JoinPoint.StaticPart</literal> which allows the AspectJ weaver to
- distinguish based on type which of
- <literal>thisJoinPointStaticPart</literal> and
- <literal>thisEnclosingJoinPointStaticPart</literal> should be passed in a given
- parameter position.
+ <literal>JoinPoint.EnclosingStaticPart</literal>
+ is a new (empty) sub-interface
+ of
+ <literal>JoinPoint.StaticPart</literal>
+ which allows the AspectJ weaver to
+ distinguish based on type which of
+ <literal>thisJoinPointStaticPart</literal>
+ and
+ <literal>thisEnclosingJoinPointStaticPart</literal>
+ should be passed in a given
+ parameter position.
</para>
<para>
- <literal>After</literal> advice declarations take exactly the same form
- as
- <literal>Before</literal>, as do the forms of
+ <literal>After</literal>
+ advice declarations take exactly the same form
+ as
+ <literal>Before</literal>
+ , as do the forms of
<literal>AfterReturning</literal>
- and
- <literal>AfterThrowing</literal> that do not expose the return type or
- thrown exception respectively.
+ and
+ <literal>AfterThrowing</literal>
+ that do not expose the return type or
+ thrown exception respectively.
</para>
<para>
- To expose a return value with after returning advice simply declare the returning
- parameter as a parameter in the method body and bind it with the "returning"
- attribute:
+ To expose a return value with after returning advice simply declare the returning
+ parameter as a parameter in the method body and bind it with the "returning"
+ attribute:
</para>
<programlisting><![CDATA[
}
]]></programlisting>
- <para>is equivalent to...</para>
+ <para>is equivalent to...</para>
<programlisting><![CDATA[
after() returning : criticalOperation() {
]]></programlisting>
<para>(Note the use of the "pointcut=" prefix in front of the pointcut
- expression in the returning case).</para>
+ expression in the returning case).</para>
<para>After throwing advice works in a similar fashion, using the
- <literal>throwing</literal> attribute when needing to expose a
- thrown exception.
+ <literal>throwing</literal>
+ attribute when needing to expose a
+ thrown exception.
</para>
<para>For around advice, we have to tackle the problem of
- <literal>proceed</literal>.
- One of the design goals for the annotation style is that a large class of
- AspectJ applications should be compilable with a standard Java 5 compiler.
- A straight call to
- <literal>proceed</literal> inside a method body:
+ <literal>proceed</literal>
+ .
+ One of the design goals for the annotation style is that a large class of
+ AspectJ applications should be compilable with a standard Java 5 compiler.
+ A straight call to
+ <literal>proceed</literal>
+ inside a method body:
</para>
<programlisting><![CDATA[
<para>will result in a "No such method" compilation error. For this
- reason AspectJ 5 defines a new sub-interface of
- <literal>JoinPoint</literal>,
- <literal>ProceedingJoinPoint</literal>.
+ reason AspectJ 5 defines a new sub-interface of
+ <literal>JoinPoint</literal>
+ ,
+ <literal>ProceedingJoinPoint</literal>
+ .
</para>
<programlisting><![CDATA[
]]></programlisting>
- <para>is equivalent to:</para>
+ <para>is equivalent to:</para>
<programlisting><![CDATA[
public aspect ProceedAspect {
]]></programlisting>
-
-<para>Note that the ProceedingJoinPoint does not need to be passed to the proceed(..) arguments.
-</para>
+ <para>Note that the ProceedingJoinPoint does not need to be passed to the proceed(..) arguments.
+ </para>
</sect2>
</sect1>
<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
- and the annotation style. We also want to support compilation of a large set
- of AspectJ applications using a standard Java 5 compiler. For these reasons, in
- the initial release of AspectJ 5 we will only support inter-type declarations
- on interfaces using the annotation style.
+ 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
+ and the annotation style. We also want to support compilation of a large set
+ of AspectJ applications using a standard Java 5 compiler. For these reasons, in
+ the initial release of AspectJ 5 we will only support inter-type declarations
+ backed by interfaces when using the annotation style - which means it is not possible to
+ introduce constructors or fields, as it would not be not possible to call those unless already
+ weaved and available on a binary form.
</para>
<para>
- Consider the following aspect:
+ Consider the following aspect:
</para>
<programlisting><![CDATA[
]]></programlisting>
<para>
- 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
+ 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).
+ is
+ <literal>Moody</literal>
+ (the target type of the inter-type declaration).
</para>
<para>Using the annotation style this aspect can be written:
@Aspect
public class MoodIndicator {
+ // this interface can be outside of the aspect
public interface Moody {
Mood getMood();
};
- @DeclareParents("org.xzy..*")
- class MoodyImpl implements Moody {
+ // this implementation can be outside of the aspect
+ public class MoodyImpl implements Moody {
private Mood mood = Mood.HAPPY;
public Mood getMood() {
}
}
+ // here is the actual ITD syntax when using @AspectJ
+ // public static is mandatory
+ // the field type must be the introduced interface. It can't be a class.
+ @DeclareParents("org.xzy..*")
+ public static Moody introduced = new MoodyImpl();
+
@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
- effect of the
- <literal>@DeclareParents</literal> annotation is equivalent to
- a declare parents statement that all types matching the type pattern implement
- the interface implemented by the annotated class. In addition, the member
- declarations within the annotated class are treated as inter-type declarations
- on the implemented interface. Note how this scheme operates within the constraints
- of Java type checking and ensures that
- <literal>this</literal> has access
- to the exact same set of members as in the code style example.
+ This is very similar to the mixin mechanism supported by AspectWerkz. The
+ effect of the
+ <literal>@DeclareParents</literal>
+ annotation is equivalent to
+ a declare parents statement that all types matching the type pattern implement
+ the interface whose @DeclareParents annotated aspect' field is type of (in this case Moody).
+ Each method declaration of this interface are treated as inter-type declarations.
+ Note how this scheme operates within the constraints
+ of Java type checking and ensures that
+ <literal>this</literal>
+ 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 whose type
+ is not an interface. Indeed, the interface is the inter-type declaration contract that dictates
+ which methods are introduced.
+ </para>
+
+ <para>
+ It is important to remember that the @DeclareParents annotated aspect' field that serves as a host
+ for the inter-type declaration must be <literal>public static</literal> and <literal>initialized by some means</literal>.
+ The weaved code will indeed delegate calls to this field when f.e. invoking:
+ </para>
+
+ <programlisting><![CDATA[
+ // this type will be affected by the inter-type declaration as the type pattern match
+ package org.xyz;
+ public class MoodTest {
+
+ public void test() {
+ // see here the cast to the introduced interface
+ Mood mood = ((Moody)this).getMood();
+ // will delegate to the aspect field "introduced" that host this inter-type declaration
+ ...
+ }
+ }
+ ]]></programlisting>
+
+ <para>
+ It is perfectly possible to use an IoC framework to initialize the @DeclaredParents aspect' field. You must
+ ensure though that the aspect field will be initialed prior the first inter-type declaration invocation it hosts.
+ </para>
+
+
+ <para>
+ If you need to only introduce a marker interface which defines no method - such as <literal>java.io.Serializable</literal>
+ it is possible to use the following syntax.
+ </para>
+
+ <para>
+ Consider the following aspect:
+ </para>
+
+ <programlisting><![CDATA[
+ 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 {
+
+ @DeclareImplements("org.xyz..*")
+ Serializable introducedNoMethods;
+ }
+ ]]></programlisting>
+
+ <para>
+ The <literal>@DeclareImplements</literal> annotation on the aspect' field dictates the type pattern
+ on which to introduce the marker interface.
</para>
- <para>The annotated class may only extend
- <literal>Object</literal>, and may
- only implement a single interface. The interface implemented by the class may
- itself extend other interfaces.
+ <para>
+ In that case, as there is no method introduced, it is perfectly possible to have the aspect' field
+ private, or not initialized. Remember that the field' type must be the introduced interface and cannot be class.
</para>
</sect1>
<title>Declare statements</title>
<para>The previous section on inter-type declarations covered the case
- of declare parents ... implements. The 1.5.0 release of AspectJ 5 will
- not support annotation style declarations for declare parents ... extends
- and declare soft (programs with these declarations would not in general
- be compilable by a regular Java 5 compiler, reducing the priority of
- their implementation). These may be supported in a future release.</para>
-
- <para>Declare precedence and declare annotation
- <emphasis>will</emphasis>
- be supported. For declare precedence, use the
+ of declare parents ... implements. The 1.5.0 release of AspectJ 5 will
+ not support annotation style declarations for declare parents ... extends
+ and declare soft (programs with these declarations would not in general
+ be compilable by a regular Java 5 compiler, reducing the priority of
+ their implementation). These may be supported in a future release.</para>
+
+ <para>
+ Declare annotation is not supported neither in the 1.5.0 release of AspectJ 5. Given that Java 5
+ compilers enforce the annotation target (@java.lang.annotation.Target) to be respected, this would cause
+ adding a lot of dummy members in the aspect (such as dummy constructors, methods etc), which would break the
+ object oriented design of the @AspectJ aspect itself.
+ </para>
+
+ <para>Declare precedence <emphasis>is</emphasis>
+ supported. For declare precedence, use the
<literal>@DeclarePrecedence</literal>
- annotation as in the following example:
+ annotation as in the following example:
</para>
<programlisting><![CDATA[
}
]]></programlisting>
+ <!--
+ note: below is not supported for now.
<para>
- Declare annotation is supported via annotations on a dummy type member. If the
- <literal>Target</literal> specification of the annotation allows it, use a field,
- otherwise declare a member of the type required by the
- <literal>Target</literal>.
- For example:
+ Declare annotation is supported via annotations on a dummy type member. If the
+ <literal>Target</literal>
+ specification of the annotation allows it, use a field,
+ otherwise declare a member of the type required by the
+ <literal>Target</literal>
+ .
+ For example:
</para>
<programlisting><![CDATA[
<para>
<emphasis>Note: Declare annotation is not available in AspectJ 1.5 M3 and syntax may change
- when the design and implementation is complete.</emphasis>
+ when the design and implementation is complete.</emphasis>
</para>
-
+ -->
<para>We also support annotation style declarations for declare warning and
- declare error - any corresponding warnings and errors will be emitted at
- weave time, not when the aspects containing the declarations are compiled.
- (This is the same behaviour as when using declare warning or error with the
- code style). Declare warning and error declarations are made by annotating
- a string constant whose value is the message to be issued.</para>
+ declare error - any corresponding warnings and errors will be emitted at
+ weave time, not when the aspects containing the declarations are compiled.
+ (This is the same behaviour as when using declare warning or error with the
+ code style). Declare warning and error declarations are made by annotating
+ a string constant whose value is the message to be issued.</para>
<para>Note that the String must be a constant and not the result of the invocation
- of a static method for example.</para>
+ of a static method for example.</para>
<programlisting><![CDATA[
declare warning : call(* javax.sql..*(..)) && !within(org.xyz.daos..*)
<title>aspectOf() and hasAspect() methods</title>
<para>A central part of AspectJ's programming model is that aspects
- written using the code style and compiled using ajc support
- <literal>aspectOf</literal> and
- <literal>hasAspect</literal> static
- methods. When developing an aspect using the annotation style and compiling
- using a regular Java 5 compiler, these methods will not be visible to the
- compiler and will result in a compilation error if another part of the
- program tries to call them.
+ written using the code style and compiled using ajc support
+ <literal>aspectOf</literal>
+ and
+ <literal>hasAspect</literal>
+ static
+ methods. When developing an aspect using the annotation style and compiling
+ using a regular Java 5 compiler, these methods will not be visible to the
+ compiler and will result in a compilation error if another part of the
+ program tries to call them.
</para>
<para>To provide equivalent support for AspectJ applications compiled with
- a standard Java 5 compiler, AspectJ 5 defines the
+ a standard Java 5 compiler, AspectJ 5 defines the
<literal>Aspects</literal>
- utility class:
+ utility class:
</para>
<programlisting><![CDATA[