@@ -37,23 +37,13 @@ | |||
<abstract> | |||
<para> | |||
This guide describes the changes to the AspectJ language | |||
and tools in AspectJ 5. These include support for Java 5 (Tiger) features, | |||
enhancements to load-time weaving, an support for an annotation-based | |||
development style for aspects. | |||
in AspectJ 5. These include support for Java 5 (Tiger) features, | |||
support for an annotation-based development style for aspects, | |||
and new reflection and tools APIs. | |||
If you are new to AspectJ, we recommend you start | |||
by reading the programming guide. | |||
</para> | |||
<para> | |||
This is a draft document and is <emphasis>subject to change</emphasis> before | |||
the design and implementation is complete. There is also no guarantee that all | |||
of the features in this document will be implemented in a 1.5.0 release - some | |||
may be deferred until 1.5.1 or even later. In general, features in which we | |||
have more confidence in the design will be implemented earlier, providing a | |||
framework for user feedback and direction setting on features for which the | |||
use cases are less obvious at time of writing. | |||
</para> | |||
</abstract> | |||
</bookinfo> | |||
@@ -69,6 +59,5 @@ | |||
&reflection; | |||
&miscellaneous; | |||
<w; | |||
&grammar; | |||
</book> |
@@ -311,21 +311,9 @@ | |||
<para> | |||
For any kind of annotated element (type, method, constructor, package, etc.), | |||
an annotation pattern can be used to match against the set of annotations | |||
on the annotated element. Annotation patterns are defined by the following | |||
grammar. | |||
</para> | |||
<programlisting><![CDATA[ | |||
AnnotationPattern := '!'? '@' AnnotationTypePattern AnnotationPattern* | |||
AnnotationTypePattern := FullyQualifiedName | | |||
'(' TypePattern ')' | |||
FullyQualifiedName := JavaIdentifierCharacter+ ('.' JavaIdentifierCharacter+)* | |||
]]></programlisting> | |||
<para>In simple terms, an annotation pattern element has one of two basic | |||
forms:</para> | |||
on the annotated element.An annotation pattern element has one of two basic | |||
forms: | |||
</para> | |||
<itemizedlist> | |||
<listitem>@<qualified-name>, for example, @Foo, or | |||
@@ -406,7 +394,7 @@ | |||
<title>Type Patterns</title> | |||
<para>AspectJ 1.5 extends type patterns to allow an optional <literal>AnnotationPattern</literal> | |||
prefix. (Extensions to this definition for generics are shown in the next chapter).</para> | |||
prefix.</para> | |||
<programlisting><![CDATA[ | |||
TypePattern := SimpleTypePattern | | |||
@@ -431,8 +419,9 @@ | |||
<para>Note that in most cases when annotations are used as part of a type pattern, | |||
the parenthesis are required (as in <literal>(@Foo Hello+)</literal>). In | |||
some cases (such as a type pattern used within a <literal>this</literal> | |||
pointcut expression, the parenthesis are optional:</para> | |||
some cases (such as a type pattern used within a <literal>within</literal> or | |||
<literal>handler</literal> | |||
pointcut expression), the parenthesis are optional:</para> | |||
<programlisting><![CDATA[ | |||
OptionalParensTypePattern := AnnotationPattern? TypePattern | |||
@@ -525,9 +514,12 @@ | |||
<sect2 id="signaturePatterns" xreflabel="Signature Patterns"> | |||
<title>Signature Patterns</title> | |||
<para>A <literal>FieldPattern</literal> is described by the following | |||
grammar:</para> | |||
<sect3 id="fieldPatterns" xreflabel="Field Patterns"> | |||
<title>Field Patterns</title> | |||
<para>A <literal>FieldPattern</literal> can optionally specify an annotation-matching | |||
pattern as the first element:</para> | |||
<programlisting><![CDATA[ | |||
FieldPattern := | |||
AnnotationPattern? FieldModifiersPattern? | |||
@@ -544,7 +536,7 @@ | |||
]]></programlisting> | |||
<para> | |||
The optional <literal>AnnotationPattern</literal> restricts matches to fields with | |||
If present, the <literal>AnnotationPattern</literal> restricts matches to fields with | |||
annotations that match the pattern. For example: | |||
</para> | |||
@@ -604,7 +596,13 @@ | |||
</variablelist> | |||
<para>A <literal>MethodPattern</literal> is of the form</para> | |||
</sect3> | |||
<sect3 id="methodPatterns" xreflabel="Method Patterns"> | |||
<title>Method and Constructor Patterns</title> | |||
<para>A <literal>MethodPattern</literal> can optionally specify an annotation-matching | |||
pattern as the first element.</para> | |||
<programlisting><![CDATA[ | |||
MethodPattern := | |||
@@ -631,8 +629,6 @@ | |||
]]></programlisting> | |||
<para><emphasis>Note: compared to the previous version, this definition of MethodPattern does | |||
not allow parameter annotation matching (only matching on annotations of parameter types).</emphasis></para> | |||
<para>A <literal>ConstructorPattern</literal> has the form</para> | |||
@@ -687,6 +683,8 @@ | |||
</listitem> | |||
</varlistentry> | |||
</variablelist> | |||
</sect3> | |||
</sect2> | |||
@@ -886,14 +884,8 @@ | |||
@args(*,*,untrustedDataSource); | |||
]]></programlisting> | |||
<para> | |||
<emphasis>Note: an alternative design would be to allow both annotation | |||
patterns and type patterns to be specified in the existing args pcd. | |||
This works well for matching, but is more awkward when it comes to | |||
exposing context.</emphasis> | |||
</para> | |||
<para>Access to <literal>AnnotatedElement</literal> information is available | |||
<para>In addition to accessing annotation information at runtime through context binding, | |||
access to <literal>AnnotatedElement</literal> information is also available | |||
reflectively with the body of advice through the <literal>thisJoinPoint</literal>, | |||
<literal>thisJoinPointStaticPart</literal>, and | |||
<literal>thisEnclosingJoinPointStaticPart</literal> variables. To access | |||
@@ -906,16 +898,6 @@ | |||
Annotation[] firstParamAnnotations = thisJoinPoint.getArgs()[0].getClass().getAnnotations(); | |||
]]></programlisting> | |||
<para> | |||
<emphasis>Note: it would be nicer to provide direct helper methods in | |||
the JoinPoint interface or a sub-interface that provide the annotations | |||
directly, something like "AnnotatedElement getThisAnnotationInfo()". | |||
The problem here is that the "AnnotatedElement" type is only in the | |||
Java 5 runtime libraries, and we don't want to tie the AspectJ runtime | |||
library to Java 5. A sub-interface and downcast solution could be used | |||
if these helpers were felt to be sufficiently important.</emphasis> | |||
</para> | |||
<para> | |||
The <literal>@within</literal> and <literal>@withincode</literal> pointcut designators | |||
match any join point where the executing code is defined within a type (<literal>@within</literal>), | |||
@@ -1009,15 +991,9 @@ | |||
<title>Package and Parameter Annotations</title> | |||
<para> | |||
<emphasis>Note: A previous design allowed package annotation patterns to be specified | |||
directly in type patterns, and parameter annotation patterns to be | |||
specified directly in method and constructor signature patterns. Because | |||
this made some pointcut expressions hard to read and understand, we moved | |||
in favour of the design presented below, which also has its drawbacks. | |||
Matching on package and parameter annotations will be | |||
deferred until after the 1.5.0 release so that we can gain more understanding | |||
of the kinds of uses AspectJ users are making of annotations in pointcut | |||
expressions before commiting to any one approach.</emphasis> | |||
<emphasis>Matching on package and parameter annotations is not supported | |||
in AspectJ 1.5.0. Support for this capability may be considered in a future | |||
release.</emphasis> | |||
</para> | |||
<!-- @withinpackage ??? --> | |||
@@ -1189,17 +1165,19 @@ | |||
</sect2> | |||
<sect2 id="limitations" xreflabel="limitations"> | |||
<title>Limitations</title> | |||
<sect2 id="matchingOnAnnotationValues" xreflabel="matchingOnAnnotationValues"> | |||
<title>Matching based on annotation values</title> | |||
<para> | |||
It would be useful to be able to match join points based on | |||
annotation values, rather than merely the presence of a | |||
class-file retention annotation of a given type. This facility may be supported in a future version of AspectJ, by expanding the | |||
definition of <literal>AnnotationPattern</literal>. Matching annotation values for | |||
annotations with runtime retention can be done by exposing the annotation value | |||
as a pointcut parameter and then using an <literal>if</literal> pointcut expression | |||
to test the value. | |||
The <literal>if</literal> pointcut designator can be used to write pointcuts | |||
that match based on the values annotation members. For example: | |||
</para> | |||
<programlisting><![CDATA[ | |||
pointcut txRequiredMethod(Tx transactionAnnotation) : | |||
execution(* *(..)) && @this(transactionAnnotation) | |||
&& if(transactionAnnotation.policy() == TxPolicy.REQUIRED); | |||
]]></programlisting> | |||
</sect2> | |||
</sect1> |
@@ -52,13 +52,6 @@ | |||
public aspect Foo {} | |||
]]></programlisting> | |||
<para>And since issingleton() is the default aspect instantiation model it is equivalent to:</para> | |||
<programlisting><![CDATA[ | |||
@Aspect("issingleton()") | |||
public class Foo {} | |||
]]></programlisting> | |||
<para>To specify an aspect an aspect instantiation model (the default is | |||
singleton), provide the perclause as the | |||
<literal>@Aspect</literal> | |||
@@ -167,8 +160,9 @@ | |||
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 (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("") | |||
@@ -254,15 +248,16 @@ | |||
</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 | |||
When using the annotation style, it is not possible to write a full Java expression | |||
within | |||
the annotation value so the syntax differs slightly, 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 | |||
, but must have either an empty body (<literal>if()</literal>, or be one | |||
of the expression forms | |||
<literal>if(true)</literal> | |||
or | |||
<literal>if(false)</literal> | |||
@@ -634,13 +629,14 @@ | |||
<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 | |||
It's very important to preserve the 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. | |||
of @AspectJ applications using a standard Java 5 compiler. For these reasons, | |||
the 1.5.0 release of AspectJ 5 only supports 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 woven and available on a binary form. | |||
</para> | |||
<para> | |||
@@ -702,11 +698,9 @@ | |||
} | |||
} | |||
// 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(); | |||
@DeclareParents(value="org.xzy..*",defaultImpl="MoodyImpl") | |||
private Moody implementedInterface; | |||
@Before("execution(* *.*(..)) && this(m)") | |||
void feelingMoody(Moody m) { | |||
@@ -721,50 +715,39 @@ | |||
<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. | |||
the given interface (in this case Moody). | |||
Each method declared in the interface is treated as an inter-type declaration. | |||
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: | |||
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 | |||
which methods are declared on the target type. | |||
</para> | |||
<programlisting><![CDATA[ | |||
// this type will be affected by the inter-type declaration as the type pattern match | |||
// 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 | |||
// see here the cast to the introduced interface (required) | |||
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>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 | |||
<literal>declare parents ... implements</literal> clause, and does <emphasis>not</emphasis> | |||
make any inter-type declarations for default implementation of the interface methods. | |||
</para> | |||
<para> | |||
@@ -785,19 +768,15 @@ | |||
@Aspect | |||
public class SerializableMarker { | |||
@DeclareImplements("org.xyz..*") | |||
Serializable introducedNoMethods; | |||
@DeclareParents("org.xyz..*") | |||
Serializable implementedInterface; | |||
} | |||
]]></programlisting> | |||
<para> | |||
The <literal>@DeclareImplements</literal> annotation on the aspect' field dictates the type pattern | |||
on which to introduce the marker interface. | |||
</para> | |||
<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. | |||
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> | |||
</sect1> | |||
@@ -806,17 +785,14 @@ | |||
<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 | |||
of declare parents ... implements. The 1.5.0 release of AspectJ 5 does | |||
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. | |||
Declare annotation is also not supported in the 1.5.0 release of AspectJ 5. | |||
</para> | |||
<para>Declare precedence <emphasis>is</emphasis> | |||
@@ -894,7 +870,7 @@ | |||
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 | |||
<para>Note that the String must be a literal and not the result of the invocation | |||
of a static method for example.</para> | |||
<programlisting><![CDATA[ | |||
@@ -912,7 +888,7 @@ | |||
@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 constant | |||
// 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() { |
@@ -850,8 +850,6 @@ | |||
<sect3> | |||
<title>Declaring pointcuts inside generic types</title> | |||
<para><emphasis>This language feature will not be supported until AspectJ 5 M4.</emphasis></para> | |||
<para>Pointcuts can be declared in both classes and aspects. A pointcut declared in a generic | |||
type may use the type variables of the type in which it is declared. All references to | |||
a pointcut declared in a generic type from outside of that type must be via a parameterized type reference, | |||
@@ -1029,8 +1027,6 @@ | |||
<sect2 id="generic-aspects" xreflabel="generic-aspects"> | |||
<title>Generic Aspects</title> | |||
<para><emphasis>This feature will not be fully implemented until AspectJ5 M4.</emphasis></para> | |||
<para> | |||
AspectJ 5 allows an <emphasis>abstract</emphasis> aspect to be declared as a generic type. Any concrete | |||
aspect extending a generic abstract aspect must extend a parameterized version of the abstract aspect. |
@@ -9,7 +9,8 @@ | |||
<sect1 id="ltw-introduction"> | |||
<title>Introduction</title> | |||
<para>See Developer's Guide.</para> | |||
<para>See Developer's Guide for information on | |||
load-time weaving support in AspectJ 5.</para> | |||
</sect1> | |||
</chapter> | |||
@@ -5,8 +5,6 @@ | |||
<sect1> | |||
<title>Pointcuts</title> | |||
<sect2 id="binding-of-formals" xreflabel="binding-of-formals"> | |||
<title>Binding of formals</title> | |||
<para> | |||
AspectJ 5 is more liberal than AspectJ 1.2.1 in accepting pointcut expressions | |||
that bind context variables in more than one location. For example, AspectJ | |||
@@ -26,16 +24,6 @@ | |||
are mutually exclusive. | |||
</para> | |||
</sect2> | |||
<sect2 id="additional-lint-warnings" xreflabel="additional-lint-warnings"> | |||
<title>Additional lint warnings</title> | |||
<para> | |||
Discuss detection of common errors -> warning/error, eg. conjunction of more than one | |||
kind of join point. Differing numbers of args in method signature / args / @args / | |||
@parameters. | |||
</para> | |||
</sect2> | |||
</sect1> | |||
<sect1 id="declare-soft"> | |||
@@ -92,17 +80,7 @@ | |||
</sect1> | |||
<sect1> | |||
<title>Tools</title> | |||
<sect2 id="aspectpath" xreflabel="aspectpath"> | |||
<title>Aspectpath</title> | |||
<para>AspectJ 5 allows the specification of directories (containing .class files) on the aspectpath in | |||
addition to jar/zip files.</para> | |||
</sect2> | |||
</sect1> | |||
</chapter> | |||
@@ -3,14 +3,25 @@ | |||
<title>New Reflection Interfaces</title> | |||
<para> | |||
AspectJ 5 provides support for runtime reflection of aspect types. The class <literal>Aspect</literal> is | |||
analogous to the Java class <literal>Class</literal> and provides access to the members of an aspect. | |||
AspectJ 5 provides a full set of reflection APIs analogous to the | |||
<literal>java.lang.reflect</literal> package, but fully aware of the | |||
AspectJ type system. See the javadoc for the runtime and tools APIs | |||
for the full details. The reflection APIs are only supported when | |||
running under Java 5 and for code compiled by the AspectJ 5 compiler | |||
at target level 1.5. | |||
</para> | |||
<sect1 id="reflection_api"> | |||
<title>The Aspect Class</title> | |||
<title>Using AjTypeSystem</title> | |||
<para> | |||
The starting point for using the reflection apis is | |||
<literal>org.aspectj.lang.reflect.AjTypeSystem</literal> which | |||
provides the method <literal>getAjType(Class)</literal> which will | |||
return the <literal>AjType</literal> corresponding to a given | |||
Java class. The <literal>AjType</literal> interface corresponds to | |||
<literal>java.lang.Class</literal> and gives you access to all of the | |||
method, field, constructor, and also pointcut, advice, declare | |||
statement and inter-type declaration members in the type. | |||
</para> | |||
</sect1> |
@@ -80,14 +80,14 @@ | |||
</varlistentry> | |||
<varlistentry> | |||
<term>-aspectpath <replaceable>JarList</replaceable></term> | |||
<term>-aspectpath <replaceable>Path</replaceable></term> | |||
<listitem><para> | |||
Weave binary aspects from JarList zip files into all sources. | |||
Weave binary aspects from Jars and directories on path into all sources. | |||
The aspects should have been output by the same version | |||
of the compiler. | |||
To run the output classes requires putting all the | |||
aspectpath entries on the run classpath. | |||
JarList, like classpath, is a single argument containing | |||
Path, like classpath, is a single argument containing | |||
a list of paths to jar files, delimited by the platform- | |||
specific classpath delimiter. | |||
</para></listitem> |