XML definition

What is important to understand is that both the Annotation and the XML definition are both just different views of the same underlying model. This means that they can easily co-exist and can succesfully be used together. The XML definition can be used as a replacement to the Annotation definition or as a complement. It can be used to refine and override definitions made in annotations as well as resolve missing pieces (for example pointcut definitions referenced but not defined) in the annotation definition. See the Choosing a definition model section for best practices.

Aspects

An aspect is defined in XML using the aspect element, which has two attributes:

  • class - specifies a fully qualified class name for the aspect implementation class.


  • deployment-model - specifies the depoyment model for the aspect. The default is perJVM if not specified
    • perJVM - deploys the aspect as perJVM.
    • perClass - deploys the aspect as perClass.
    • perInstance - deploys the aspect as perInstance.
    • perThread - deploys the aspect as perThread.

Inside the aspect elements you then define the poincuts, advice and introductions.

Pointcuts

The pointcut is the construct that picks out join points, i.e. selects sets of well-defined points in the program flow. In the XML defintion pointcuts are defined using the pointcut element.

When defining a pointcut there are two attributes that needs to be specified:

  • name - specifies the name of the pointcut. Needs to be composed of a first part also called pointcut name, unique throughout the aspect defininition, and an optional second part called the pointcut signature : name="<pointcut name>[(<pointcut signature>)]". The signature must name its parameters (as if it was some source code).

    Caution: pointcut names must only consist of these characters: [A-Z], [a-z], [0-9] and the characters $ and _ (not for example - or /).

    The optional pointcut signature must be compatible with the args() selector when used. The abbreviations for java.lang.* can be used as described here.
  • expression - specifies the expression for the pointcut. This is the pattern that picks out the join points that should be included in the pointcut. This attribute is "optional". If not specified, the <pointcut> element must have the expression in its body.

    See the Join point selection pattern language section for a detailed description on how these patterns are written and see the Pointcut definition and Pointcut composition sections for details on how pointcuts are defined and composed.



Example of some pointcut definitions:

<aspect ...>
    <pointcut name="pc1" expression="execution(* foo.Bar.method(..))"/>
    <pointcut name="pc2" expression="set(* foo.Bar.m_field)"/>
    <pointcut name="pc3" expression="get(* foo.Bar.m_field)"/>
    <pointcut name="pc4" expression="handler(java.lang.Exception)AND withincode(foo.bar.*.new(..))"/>
    <pointcut name="pc5" expression="call(String foo.Callee.method()) AND within(foo.bar.*)"/>
    <pointcut name="pc6" expression="cflow(execution(* Transaction.begin(..)))"/>
    ...
    <!-- do not use a pointcut name more than once (pcArg1) -->
    <pointcut name="pcArg1(String s)" expression="execution(* foo.Bar.method(..)) AND args(s, ..)"/>
    <pointcut name="pcArg1Same(String s)" expression="pc1 AND args(s, ..)"/>
    <pointcut name="pcArg1Other(com.Foo foo, String[] s)" expression="execution(* foo.Bar.method(..)) AND args(foo, int, .., s)"/>

    <!-- use element body instead -->
    <pointcut name="pcMultiLine">
        execution(int com.Do.foo(..))
        OR execution(int come.Done.bar(..))
    </pointcut>
</aspect>
                

System wide pointcuts

The pointcuts can also be "system-wide", which means that you can define pointcuts outside the aspects, within the system tags. These can then be used by all aspects in the system defintion.

Advice

In the XML defintion advice are defined using the advice element.

When defining the advice there are three attributes that needs to be specified:

  • name - the name of the advice is the name of the method in the aspect class that implements the advice, with a optional method signature if pointcut with signature are used. Abbreviations can be used in this signature, including for the JoinPoint parameter. The signature must name its parameters (as if it was some source code) like advice3(JoinPoint jp, int i). The method defined this way must exist with the same signature in the aspect class hierarchy.


  • type - the type defines the type of the advice. Valid types are:
    • around - defines an around advice
    • before - defines an before advice
    • after - defines an after advice


  • bind-to - binds the advice to a pointcut by referencing the name of the pointcut or by defining an anonymous pointcut. If the pointcut has a signature (with args() selector), then those must be refered as named in the advice name signature part.


Example:

<advice name="advice1"
        type="before"
        bind-to="(pc1 || pc2) AND pc3"/>

<advice name="advice2"
        type="around"
        bind-to="execution(int examples.caching.Pi.getPiDecimal(int))"/>

<advice name="advice3(JoinPoint jp, int i)"
        type="around"
        bind-to="pc1 AND args(i, String[], foo.Bar)"/>

<advice name="advice4(org.codehaus.aspectwerkz.joinpoint.JoinPoint jp, int i)"
        type="around"
        bind-to="execution(int examples.caching.Pi.getPiDecimal(..)) AND args(i)"/>
                 

Introductions

When defining the mixin there are two attributes that needs to be specified:

  • class - the class name of the mixin


  • bind-to - binds the mixin to a class using the within(...), hasmethod(...) and/or hasfield(...) pointcuts


XML definition

<aspect ...>
    ...
    <introduce class="IntroductionTestAspect$MyImpl" bind-to="within(test.ToBeIntroduced)"/>
    ...
</aspect>
                

Passing parameters to aspects

You also have the option of passing parameters to your aspects. This can be very convenient if you want to reuse the same aspect but with a different configuration without using aspect inheritance. To pass a parameter to the aspect you simply add a param tag to the aspect definition, like this:

<aspect ... >
    <param name="timeout" value="10"/>
</aspect>
                

From within an Aspect subclass use the method ___AW_getParameter("timeout") to retrieve the parameter value as a String.

Package namespaces

Package namespaces provide a way to simplify the edition of the XML definition file so that it is not necessary to prefix all class with the complete package information.

You have two ways of defining a package namespace:

  • using the base-package attribute in the system element. This defines a global package namespace for all elements defined within the system element.


  • using the package element. This element has one attribute; name, which defines the package namespace.
The package name will be used as a prefix for all nested elements.

Example

<aspectwerkz>
    <system id="foodemo" base-package="foo">
        <!-- All classes are prefixed by 'foo' -->

        <package name="bar">
            <!-- All classes within these 'package' tags are prefixed by 'foo.bar' -->
        </package>

        <package name="baz.buzz">
            <!-- All classes within these 'package' tags are prefixed by 'foo.baz.buzz' -->
        </package>
    </system>
</aspectwerkz>
                

Transformation scopes

Using transformation scopes you can choose to perform the transformation within certain packages only. E.g. filter out all classes from all other packages in the transformation process. This can speed up the transformation process a lot as well as assure you that only classes within the packages you have defined is getting transformed no matter how freely you define your pointcut patterns.

A transformation scope is defined using the exclude and include element which have one attribute package where you define the package name. You can define as many transformation scopes as you want.

The package attribute supports only .* as an ending pattern (package and all sub package).

During the transformation process (online or offline), a class might be transformed (depending on the pointcuts) if

  1. the class does not belongs to any exclude packages if any
  2. and
  3. the class belongs to at least one include packages if any
Note that when include is used the selection is much more restrictive. This selection mechanism should be used as most as possible especially in online mode since it enables an ealry filtering.

Example

<aspectwerkz>
    <system id="sample">
        <!--
            Transformations will only take place within the 'org.codehaus.package' package and its subpackages
        -->
        <include package="org.codehaus"/>
        <include package="org.codehaus.*"/> <!-- synonymous of org.codehaus -->
        <exclude package="com.oracle.*"/>
        ...
    </system>
</aspectwerkz>
                

DTD for XML definition

Each distribution comes with a bundled DTD so that it is not looked for on the web at runtime. The XML is not validated against its DTD at runtime so be cautious to provide a valid XML defintion.

When you write your XML definition file, add the following at the top of your XML to reference the latest release:

<!DOCTYPE aspectwerkz PUBLIC
    "-//AspectWerkz//DTD//EN"
    "http://aspectwerkz.codehaus.org/dtd/aspectwerkz.dtd">
            

It is possible to specify a specific released version number as well (starting with 0.8)

<!DOCTYPE aspectwerkz PUBLIC
    "-//AspectWerkz//DTD 1.0//EN"
    "http://aspectwerkz.codehaus.org/dtd/aspectwerkz_1_0.dtd">
                

Example of an XML definition

Here is an example where all the definitions are put together into a single AspectWerkz XML definition file.

<aspectwerkz>
    <system id="sample">

        <pointcut name="systemWide" expression="execution(int com.Do.foo(..))"/>

        <pointcut name="mutliLine">
            call(int com.Do.foo(..))
            AND within(com.ToDO)
        </pointcut>

        <package name="examples">

            <aspect class="caching.CachingAspect" deployment-model="perInstance">
                <param name="timeout" value="10"/>

                <introduce class="IntroductionTestAspect$MyImpl"
                           bind-to="within(test.ToBeIntroduced)"/>

                <pointcut name="callee"
                          expression="execution(int examples.caching.Pi.getPiDecimal(int))"/>

                <pointcut name="caller"
                          expression="call(int examples.caching.Pi.getPiDecimal(int)) && within(examples.caching.*)"/>

                <advice name="invocationCounter"
                        type="before"
                        bind-to="caller"/>

                <advice name="cache"
                        type="around"
                        bind-to="callee"/>

                <!-- use of args() -->
                <pointcut name="calleeArgFiltered(int i)"
                          expression="callee AND args(i)"/>

                <advice name="traceArg(JoinPoint jp, int theArg)"
                        type="around"
                        bind-to="calleeArgFiltered(theArg)"/>

            </aspect>
        </package>
    </system>
</aspectwerkz>