Browse Source

updates for ltw and annotations

tags/Root_AspectJ5_Development
acolyer 19 years ago
parent
commit
0c83150870

+ 7
- 2
docs/adk15ProgGuideDB/adk15notebook.xml View File

@@ -11,6 +11,8 @@
<!ENTITY covariance SYSTEM "covariance.xml">
<!ENTITY varargs SYSTEM "varargs.xml">
<!ENTITY pertypewithin SYSTEM "pertypewithin.xml">
<!ENTITY ltw SYSTEM "ltw.xml">
<!ENTITY ataspectj SYSTEM "ataspectj.xml">
<!ENTITY miscellaneous SYSTEM "miscellaneous.xml">
<!ENTITY reflection SYSTEM "reflection.xml">
<!ENTITY grammar SYSTEM "grammar.xml">]>
@@ -35,8 +37,9 @@
<abstract>
<para>
This guide describes the changes to the AspectJ language
and tools in AspectJ 5. These changes are primarily, but not exclusively,
to support Java 5 (Tiger) features.
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.
If you are new to AspectJ, we recommend you start
by reading the programming guide.
</para>
@@ -62,8 +65,10 @@
&varargs;
&enumeratedtypes;
&pertypewithin;
&ataspectj;
&reflection;
&miscellaneous;
&ltw;
&grammar;

</book>

+ 655
- 0
docs/adk15ProgGuideDB/ataspectj.xml View File

@@ -0,0 +1,655 @@
<chapter id="ataspectj" xreflabel="AtAspectJ">

<title>An Annotation Based Development Style</title>
<sect1 id="ataspectj-intro">
<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>
<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.
</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.
</para>
</sect1>
<sect1 id="ataspectj-aspects">
<title>Aspect Declarations</title>
<para>
Aspect declarations are supported by the
<literal>org.aspectj.lang.annotation.Aspect</literal> annotation.
The declaration:
</para>
<programlisting><![CDATA[
@Aspect
public class Foo {}
]]></programlisting>
<para>Is equivalent to:</para>

<programlisting><![CDATA[
public aspect Foo {}
]]></programlisting>

<para>Privileged aspects are declared as:</para>

<programlisting><![CDATA[
@Aspect(isPrivileged=true)
public class Foo {}
is equivalent to...
public privileged aspect Foo {}
]]></programlisting>

<para>To specify an aspect an aspect instantiation model (the default is
singleton), use the <literal>instantionModel</literal> and
<literal>perClausePattern</literal> attributes. For example:</para>
<programlisting><![CDATA[
@Aspect(instantiationModel=AspectInstantiationModel.PERTHIS,
perClausePattern="execution(* abc..*(..))")
public class Foo {}
is equivalent to...
public aspect Foo perthis(execution(* abc..*(..))) {}
]]></programlisting>
<para>The full definitions of the Aspect annotation type and the
AspectInstantiationModel enumerated type are:</para>

<programlisting><![CDATA[
/**
* Use to indicate that a class should be treated as an aspect by
* AspectJ's weaver.
*/
@Target({ElementType.TYPE})
public @interface Aspect {
AspectInstantiationModel instantiationModel() default AspectInstantiationModel.SINGLETON;
String perClausePattern() default "";
boolean isPrivileged() default false;
}
/**
* The different aspect instantiation models supported by AspectJ
*/
public enum AspectInstantiationModel {
SINGLETON,
PERTHIS,
PERTARGET,
PERCFLOW,
PERCFLOWBELOW,
PERTYPEWITHIN
}
]]></programlisting>

</sect1>
<sect1 id="ataspectj-pcadvice">
<title>Pointcuts and Advice</title>
<para>
Pointcut and advice declarations can be made using the
<literal>Pointcut, Before, After, AfterReturning, AfterThrowing,</literal>
and <literal>Around</literal> annotations.
</para>
<sect2>
<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 <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. The method body should be empty and there should be no
throws clause.
</para>
<para>A simple example:</para>

<programlisting><![CDATA[
@Pointcut("call(* *.*(..))")
void anyCall() {}
is equivalent to...
pointcut anyCall() : call(* *.*(..));
]]></programlisting>
<para>An example with modifiers:</para>
<programlisting><![CDATA[
@Pointcut("")
protected abstract void anyCall();
is equivalent to...
protected abstract pointcut anyCall();
]]></programlisting>
<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 java.lang). This
to 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;
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
@Aspect
public class Foo {
@Pointcut("call(* java.util.List.*(..))") // must qualify
void listOperation() {}
@Pointcut("call(* java.util..*(..))")
void anyUtilityCall() {}
}
]]></programlisting>
<para>The <literal>value</literal> attribute of the
<literal>Pointcut</literal> declaration may contain any valid
AspectJ pointcut declaration.</para>
</sect2>
<sect2>
<title>Advice</title>
<para>In this section we first discuss the use of annotations for
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.</para>
<para>Using the annotation style, an advice declaration is written as
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.</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), and the restriction that advice cannot be
invoked explicitly (the weaver will issue an error if an advice method
is explicitly invoked).</para>
<para>The following example shows a simple before advice declaration in
both styles:</para>

<programlisting><![CDATA[
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>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>

<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>
<para>If the advice body needs to know which particular <literal>Foo</literal>
was doing the calling, just add a parameter to the advice declaration.</para>

<programlisting><![CDATA[
@AdviceName("callFromFoo")
before(Foo foo) : call(* org.aspectprogrammer..*(..)) && this(foo) {
System.out.println("Call from Foo: " + foo);
}
is equivalent to...
@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>,
<literal>thisJoinPointStaticPart</literal>,
<literal>thisEnclosingJoinPointStaticPart</literal> then these need to
be declared as additional method parameters when using the annotation
style. 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.</para>

<programlisting><![CDATA[
@AdviceName("callFromFoo")
before(Foo foo) : call(* org.aspectprogrammer..*(..)) && this(foo) {
System.out.println("Call from Foo: " + foo + " at "
+ thisJoinPoint);
}
is equivalent to...
@Before("call(* org.aspectprogrammer..*(..)) && this(foo)")
public void callFromFoo(JoinPoint thisJoinPoint, Foo foo) {
System.out.println("Call from Foo: " + foo + " at "
+ thisJoinPoint);
}
]]></programlisting>
<para>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>
<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.
</para>
<para><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.</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:
</para>
<programlisting><![CDATA[
after() returning : criticalOperation() {
System.out.println("phew");
}
after() returning(Foo f) : call(Foo+.new(..)) {
System.out.println("It's a Foo: " + f);
}
can be written as...
@AfterReturning("criticalOperation()")
public void phew() {
System.out.println("phew");
}
@AfterReturning(value="call(Foo+.new(..))",returning="f")
public void itsAFoo(Foo f) {
System.out.println("It's a Foo: " + f);
}
]]></programlisting>
<para>(Note the need for the "value=" prefix in front of the pointcut
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.</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:</para>

<programlisting><![CDATA[
@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
reason AspectJ 5 defines a new sub-interface of <literal>JoinPoint</literal>,
<literal>ProceedingJoinPoint</literal>. </para>
<programlisting><![CDATA[
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>
<para>Here's an example that uses parameters for the proceed call:</para>

<programlisting><![CDATA[
public aspect ProceedAspect {
pointcut setAge(int i): call(* setAge(..)) && args(i);
Object around(int i): setAge(i) {
return proceed(i*2);
}
}
can be written as...
@Aspect
public class ProceedAspect {
@Pointcut("call(* setAge(..)) && args(i)")
void setAge(int i) {}
@Around("setAge(i)")
public Object twiceAsOld(ProceedingJoinPoint thisJoinPoint, int i) {
return thisJoinPoint.proceed(i*2);
}
}
]]></programlisting>
</sect2>
</sect1>
<sect1 id="ataspectj-itds">
<title>Inter-type Declarations</title>
<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.
</para>
<para>
Consider the following aspect:
</para>
<programlisting><![CDATA[
public aspect MoodIndicator {
public interface Moody {};
private Mood Moody.mood = Mood.HAPPY;
public Mood Moody.getMood() {
return mood;
}
declare parents : org.xyz..* implements Moody;
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 - 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).
</para>
<para>Using the annotation style this aspect can be written:
</para>

<programlisting><![CDATA[
@Aspect
public class MoodIndicator {
public interface Moody {
Mood getMood();
};
@DeclareParents("org.xzy..*")
class MoodyImpl implements Moody {
private Mood mood = Mood.HAPPY;
public Mood getMood() {
return mood;
}
}

@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.</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>
</sect1>
<sect1 id="ataspectj-declare">
<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 <literal>@DeclarePrecedence</literal>
annotation as in the following example:</para>

<programlisting><![CDATA[
public aspect SystemArchitecture {
declare precedence : Security*, TransactionSupport, Persistence;
// ...
}
can be written as:
@Aspect
@DeclarePrecedence("Security*,org.xyz.TransactionSupport,org.xyz.Persistence")
public class SystemArchitecture {
// ...
}
]]></programlisting>
<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:
</para>
<programlisting><![CDATA[
public aspect DeclareAnnotationExamples {
declare annotation : org.xyz.model..* : @BusinessDomain;
declare annotation : public * BankAccount+.*(..) : @Secured(role="supervisor");
declare anotation : * DAO+.* : @Persisted;
}
can be written as...
@Aspect
public class DeclareAnnotationExamples {
@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();
@DeclareAnnotation("* DAO+.*")
@Persisted Object daoFields;
}
]]></programlisting>
<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>
<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";
can be written as...
@DeclareWarning("call(* javax.sql..*(..)) && !within(org.xyz.daos..*)")
static final String aMessage = "Only DAOs should be calling JDBC.";
@DeclareError("execution(* IFoo+.*(..)) && !within(org.foo..*)")
static final String badIFooImplementors = "Only foo types can implement IFoo";
]]></programlisting>
</sect1>
<sect1 id="ataspectj-aspectof">
<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.</para>
<para>To provide equivalent support for AspectJ applications compiled with
a standard Java 5 compiler, AspectJ 5 defines the <literal>Aspects</literal>
utility class:
</para>
<programlisting><![CDATA[
public class Aspects {
/* 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 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 perthis, pertarget */
public static boolean hasAspect(Object anAspect, Object forObject) {...}
/* variation used for pertypewithin */
public static boolean hasAspect(Object anAspect, Class forType) {...}
}
]]></programlisting>
<para>When the AspectJ weaver sees calls to these methods, it will convert
them into the most efficient form possible (to get performance equivalent
to a direct <literal>MyAspect.aspectOf()</literal> call).</para>
</sect1>
</chapter>


+ 361
- 0
docs/adk15ProgGuideDB/ltw.xml View File

@@ -0,0 +1,361 @@
<chapter id="ltw" xreflabel="Load-Time Weaving">
<title>Load-Time Weaving</title>
<sect1 id="ltw-introduction">
<title>Introduction</title>
<para> The AspectJ 5 weaver takes class files as input and produces class files as output.
The weaving process itself can take place at one of three different times: compile-time,
post-compile time, and load-time. The class files produced by the weaving process (and
hence the run-time behaviour of an application) are the same regardless of the approach
chosen. </para>
<itemizedlist>
<listitem> Compile-time weaving is the simplest approach. When you have the source code
for an application, ajc will compile from source and produce woven class files as
output. The invocation of the weaver is integral to the ajc compilation process. The
aspects themselves may be in source or binary form. </listitem>
<listitem> Post-compile weaving (also sometimes called binary weaving) is used to weave
existing class files and JAR files. As with compile-time weaving,
the aspects used for weaving may be in source or binary form. </listitem>
<listitem> Load-time weaving (LTW) is simply binary weaving defered until the point that
a class loader loads a class file and defines the class to the JVM. To support this,
one or more "weaving class loaders", either provided explicitly by the run-time
environment or enabled through a "weaving agent" are required. </listitem>
</itemizedlist>
<para> You may also hear the term "run-time weaving". We define this as the weaving of
classes that have already been defined to the JVM (without reloading those
classes). AspectJ 5 does not provide explicit support for run-time weaving although
simple coding patterns can support dynamically enabling and disabling advice in aspects. </para>
<sect2>
<title>Weaving class files more than once</title>
<para> By default a class file that has been woven by the AspectJ compiler cannot
subsequently be rewoven (passed as input to the weaver). If you are developing
AspectJ applications that are to be used in a load-time weaving environment, you
need to specify the <literal>-Xreweavable</literal> compiler option when building
them. This causes AspectJ to save additional state in the class files that is used
to support subsequent reweaving. </para>
</sect2>
</sect1>
<sect1 id="ltw-rules">
<title>Load-time Weaving Requirements</title>
<para> All load-time weaving is done in the context of a class loader, and hence the set of
aspects used for weaving and the types that can be woven are affected by the class
loader delegation model. This ensures that LTW complies with the Java 2 security model.
The following rules govern the interaction of load-time weaving with class loading: </para>
<orderedlist>
<listitem> All aspects to be used for weaving must be defined to the weaver before any
types to be woven are loaded.</listitem>
<listitem> All abstract and concrete aspects visible to the weaver
are available for extending (abstract aspects) and using for weaving.
A visible aspect is one defined by the
weaving class loader or one of its parent class loaders.</listitem>
<listitem>A class loader may only weave classes that it defines. It may not weave
classes loaded by a delegate or parent class loader.</listitem>
</orderedlist>
</sect1>
<sect1 id="ltw-configuration">
<title>Configuration</title>
<para>AspectJ 5 supports a number of mechanisms designed to make load-time weaving as
easy to use as possibe. The load-time weaving mechanism is chosen through JVM startup options.
Configuration files determine the set of aspects to be used for weaving and which
types will be woven. Additional diagnostic options allow the user to debug the configuration and
weaving process. </para>
<sect2>
<title>Enabling Load-time Weaving</title>
<para> AspectJ 5 supports three different ways of enabling load-time weaving for
an application: agents, a command-line launch script, and a set of interfaces for
integration of AspectJ load-time weaving in custom environments. </para>
<variablelist>
<varlistentry>
<term>Agents</term>
<listitem>
<para>AspectJ 5 ships with a number of load-time weaving agents that
enable load-time weaving. These agents and their configuration
are execution environment dependent.
Using Java 5 for example, you can specify the "-javaagent" option
to the JVM. Configuration for the supported environments is discussed
later in this chapter. AspectJ 5
has several agents including those that use JVMTI, and the
JRockit MAPI. </para>
</listitem>
</varlistentry>
<varlistentry>
<term>Command line</term>
<listitem>
<para> AspectJ includes a script "aj" that allows programs executed at
the command line to take advantage of load-time weaving.
The script is customized when AspectJ is installed depending on the chosen
JDK. For example, for JDK 1.4 the script uses the
<literal>-Djava.system.class.loader</literal> system property to replace
the system class loader with a weaving class loader allowing classes
loaded from the CLASSPATH to be woven.
For JDK 1.5 the JVMTI weaving agent is used allowing classes loaded by all
class loaders to be woven. Versions of the JDK prior to 1.3 are not
supported by the "aj" mechanism. </para>
</listitem>
</varlistentry>
<varlistentry>
<term>Custom Integration</term>
<listitem>
<para> A public interface is provided to allow a user written class loader
to instantiate a weaver and weave classes after loading and before
defining them in the JVM. This enables load-time weaving to be supported in
environments where no weaving agent is available. It also allows the
user to explicity restrict by class loader which classes can be woven. </para>
</listitem>
</varlistentry>
</variablelist>
</sect2>
<sect2>
<title>Configuring Load-time Weaving with aop.xml files</title>
<para>The weaver is configured using one or more <literal>META-INF/aop.xml</literal>
files located on the class loader search path. Each file may define a list of
concrete aspects to be used for weaving, type patterns describing which types
should woven, and a set of options to be passed to the weaver. In addition AspectJ 5
supports the definition of concrete aspects in XML. Aspects defined in this way
must extend an abstract aspect visible to the weaver. The abstract aspect
may define abstract pointcuts (but not abstract
methods). The following example shows a simple aop.xml file: </para>
<programlisting><![CDATA[
<aspectj>
<aspects>
<!-- declare two existing aspects to the weaver -->
<aspect name="com.MyAspect"/>
<aspect name="com.MyAspect.Inner"/>

<!-- define a concrete aspect inline -->
<concrete-aspect name="com.xyz.tracing.MyTracing" extends="tracing.AbstractTracing">
<pointcut name="tracingScope" expression="within(org.maw.*)"/>
</concrete-aspect>
<!-- Of the set of aspects known to the weaver, use aspects matching
the type pattern "com..*" for weaving. -->
<include within="com..*"/>
<!-- Do not use any aspects with the @CoolAspect annotation for weaving -->
<exclude within="@CoolAspect *"/>
</aspects>

<weaver options="-verbose -XlazyTjp">
<!-- Weave types that are within the javax.* or org.aspectj.*
packages. Also weave all types in the foo package that do
not have the @NoWeave annotation. -->
<include within="javax.*"/>
<include within="org.aspectj.*"/>
<include within="(!@NoWeave foo.*) AND foo.*"/>
</weaver>
</aspectj>
]]></programlisting>
<para>
An aop.xml file contains two key sections: "aspects" defines one
or more aspects to the weaver and controls which aspects are to be
used in the weaving process; "weaver" defines weaver options and which
types should be woven.
</para>
<para>
The simplest way to define an aspect to the weaver is to
specify the fully-qualified name of the aspect type in an aspect element.
You can also
declare (and define to the weaver) aspects inline in the aop.xml file.
This is done using the "concrete-aspect" element. A concrete-aspect
declaration must provide a pointcut definition for every abstract
pointcut in the abstract aspect it extends. This mechanism is a
useful way of externalizing configuration for infrastructure and
auxiliary aspects where the pointcut definitions themselves can be
considered part of the configuration of the service.
</para>
<para>
The aspects element may optionally contain one or more include and
exclude elements (by default, all defined aspects are used for weaving).
Specifying include or exclude elements restricts the set of defined
aspects to be used for weaving to those that are matched by an include
pattern, but not by an exclude pattern. The 'within' attribute accepts
a type pattern of the same form as a within pcd, except that &amp;&amp;
and || are replaced by 'AND' and 'OR'.
</para>
<para>
The weaver element is used to pass options to the weaver and to specify
the set of types that should be woven. If no include elements are specified
then all types seen by the weaver will be woven.
</para>
<para> When several configuration files are visible from a given weaving class loader
their contents are conceptually merged (this applies to both aop.xml files
and to aop.properties files as described in the next section).
The files are merged in the order they are
found on the search path (regular <literal>getResourceAsStream</literal> lookup)
according to the following rules: </para>
<itemizedlist>
<listitem> The set of available aspects is the set of all
declared and defined aspects (<literal>aspect</literal> and
<literal>concrete-aspect</literal> elements of the <literal>aspects</literal>
section).</listitem>
<listitem>The set of aspects used for weaving is the subset of the available
aspects that are matched by at least one include statement and are not matched
by any exclude statements. If there are no include statements then all non-excluded
aspects are included.</listitem>
<listitem> The set of types to be woven are those types matched by at
least one weaver <literal>include</literal> element and not matched by any
weaver <literal>exclude</literal> element. If there are no weaver include
statements then all non-excluded types are included.</listitem>
<listitem> The weaver options are derived by taking the union of the
options specified in each of the weaver options attribute specifications. Where an
option takes a value e.g. <literal>-warn:none</literal> the most recently defined value
will be used.</listitem>
</itemizedlist>

<para>It is not an error for the same aspect to be defined to the weaver in
more than one visible <literal>META-INF/aop.xml</literal> file.
However, if a declarative concrete aspect
is declared in more than aop.xml file then an error will be issued.
A concrete aspect
defined in this way will be used to weave types loaded by the
class loader that loaded the aop.xml file in which it was defined.
</para>
<para> A <literal>META-INF/aop.xml</literal> file will automatically be generated when
using the <literal>-outjar</literal> option of the AspectJ compiler.
It will simply contain a (possibly empty) set of aspect elements, one for
each concrete aspect included in the JAR. </para>
</sect2>
<sect2>
<title>Configuring Load-time Weaving with Properties Files</title>
<para> For memory constrained environments or those without support for XML a simple
Java Properties file can be used to configure LTW. Just like XML files,
<literal>META-INF/aop.properties</literal> files are loaded from the class loader
search path. Everything that can be configured through XML can be configured using a
Properties file, with the exception of declarative concrete aspects. For example: </para>
<programlisting><![CDATA[
aspects.names=com.MyAspect,com.MyAspect.Inner
aspects.include=com..*
aspects.exclude=@CoolAspect

weaver.options=-verbose -XlazyTjp
weaver.include=javax.* OR org.aspectj.*
]]></programlisting>
</sect2>
<sect2>
<title>Weaver Options</title>
<para> The table below lists the AspectJ options supported by LTW. All other options
will be ignored and a warning issued. </para>
<informaltable>
<tgroup cols="2">
<thead>
<row>
<entry>Option</entry>
<entry>Purpose</entry>
</row>
</thead>
<tbody>
<row>
<entry>
<literal>-1.5</literal>
</entry>
<entry>Run the weaver in 1.5 mode (supports autoboxing in
join point matching)</entry>
</row>
<row>
<entry>
<literal>-XlazyTjp</literal>
</entry>
<entry>Performance optimization for aspects making use
of thisJoinPoint (non-static parts)</entry>
</row>
<row>
<entry>
<literal>-nowarn, -warn:none</literal>
</entry>
<entry>Suppress warning messages</entry>
</row>
<row>
<entry>
<literal>-proceedOnError</literal>
</entry>
<entry>Continue weaving even if errors occur (for example,
"... already woven" errors)</entry>
</row>
<row>
<entry>
<literal>-verbose</literal>
</entry>
<entry>Issue informational messages about the weaving process</entry>
</row>
<row>
<entry>
<literal>-Xreweavable</literal>
</entry>
<entry>Produce class files that can subsequently be rewoven</entry>
</row>
<row>
<entry>
<literal>-Xnoinline</literal>
</entry>
<entry>Don't inline around advice.</entry>
</row>
<row>
<entry>
<literal>-showWeaveInfo</literal>
</entry>
<entry>Issue informational messages whenever the weaver touches a class file</entry>
</row>
<row>
<entry>
<literal>-XmessageHolderClass</literal>
</entry>
<entry>Provide alternative output destination to stderr for all weaver messages</entry>
</row>
</tbody>
</tgroup>
</informaltable>
</sect2>
</sect1>
<sect1 id="ltw-packaging">
<title>Runtime Requirements for Load-time Weaving</title>
<para> To use LTW the <literal>aspectjweaver.jar</literal> library must be added to the
classpath. This contains the AspectJ 5 runtime, weaver, weaving class loader and
weaving agents. It also contains the DTD for parsing XML weaving configuration files. </para>
</sect1>
<sect1 id="ltw-agents">
<title>Supported Agents</title>
<sect2>
<title>JVMTI</title>
<para> When using JDK 1.5 the JVMTI agent can be used by starting the JVM with the
following option: </para>
<programlisting><![CDATA[
-javaagent=aspectjweaver.jar
]]></programlisting>
</sect2>
<sect2>
<title>JRockit</title>
<para> The JRockit agent is configured with the following JVM option: </para>
<programlisting><![CDATA[
-Xmanagement:class=org.aspectj.weaver.tools.JRockitWeavingAgent
]]></programlisting>
</sect2>
</sect1>
</chapter>

Loading…
Cancel
Save