AspectWerkz - Plain Java AOP

##### General Information

- Overview
- Features
- License
- Downloads

##### Documentation

- New features in 2.x
- Introduction
- Tutorials
- Implementation issues
- General definition issues
- Annotation definition
- XML definition
- Annnotation driven development
- Deployment
- Weaving
- Dynamic AOP
- AOP container extensions
- Examples
- IDE integration
- JavaDoc
- FAQ

##### Misc.

- Releases & Release notes
- Build & install
- CVS access
- Mailing lists
- Tasks
- Papers, articles & talks

##### Project Documentation

- About AspectWerkz - Plain Java AOP
- Project Info
- Project Reports
- Development Process

## Annotation definition

What is important to understand is that both the Annotation and the XML definition are 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.

AspectWerkz fully supports Java 5 annotations to define aspects or simply match on, and provides a Java 1.3/1.4 annotation API and custom compiler that allows to use the same feature with a very close user experience. Strongly typed Java 1.3/1.4 annotations facilities is thus provided.

## Table of Contents

1. Aspects
2. Pointcuts
3. Advice
4. Introductions
5. Annotation reference
6. Aspect annotation compilation
7. XML deployment descriptor

## Aspects

Even if all definition is made using annotations (and nothing in XML) a tiny deployment descriptor in XML still has to be written. This is needed for the runtime system to know which aspects it should load. See the XML deployment descriptor section for more information on how to write such a deployment descriptor.

When defining an aspect using annotations, the deployment model is specified as metadata argument of the metadata tag `@Aspect`.

`@Aspect` class level metadata has an optional anonymous parameter which specifies the deployment model. The default is `perJVM` if not specified.

- `@Aspect("perJVM")` - deploys the aspect as perJVM. This is the default if only `@Aspect` is specified.
- `@Aspect("perClass")` - deploys the aspect as perClass.
- `@Aspect("perInstance")` - deploys the aspect as perInstance.
- an optional `name=` named parameter which specify the name of the aspect. The default is the aspect class name if not specified.

It is also possible to not declare the `@Aspect` at all and define the deployment model in the XML descriptor.

### Pointcut definition

In the aspect class you put the pointcut definitions as fields of the type `org.codehaus.aspectwerkz.definition.Pointcut` along with metadata annotations which specifies the type of (staticinitialization, execution, call, set, get, cflow or handler) and pattern for the pointcut.
If the pointcut is used to retain parameters value of the matching target (method/constructor execution/call and field value set) it has to be defined as a method, with a signature that conforms to the `args()` selector in the expression. For details see the Pointcuts section.

### Advice definition

Define the type of the advice using annotation for the method along with the pointcut to which it the advice should be bound.

One of `@Around`, `@Before`, `@After`, `@AfterFinally`, `@AfterReturning` or `@AfterThrowing` annotations needs to be is specified. For details see the Advice section.

Source sample

The following source sample gives the main ideas of the annotation defined Aspect.

Java 5 annotations

    @Aspect("perInstance")
    public class MyAspect {

        @Introduce("within(com.mypackage.*)")
        MarkerInterface anIntroduction;

        @Expression("execution(* com.mypackage.Target.*(..))")
        Pointcut pc1;

        @Around("pc1")
        public Object advice1(final JoinPoint joinPoint) throws Throwable {
            // do some stuff
            Object result = joinPoint.proceed();
            // do some other stuff
            return result;
        }

         @Around("call(* com.mypackage.Target.*(..))")
        public Object advice2(final JoinPoint joinPoint) throws Throwable {
            // do some stuff
            Object result = joinPoint.proceed();
            // do some other stuff
            return result;
        }

        @Mixin("within(com.mypackage..*)")
        public static class MyIntroduction extends SuperMixin implements ContractualInterface {
            ... // introduced methods and fields
        }
    }

JavaDoc annotations

    /**
     * @Aspect("perInstance")
     */
    public class MyAspect {

        /**
         * @Introduce("within(com.mypackage.*)")
         */
        MarkerInterface anIntroduction;

        /**
         * @Expression("execution(* com.mypackage.Target.*(..))")
         */
        Pointcut pc1;

        /**
         * @Around("pc1")
         */
        public Object advice1(final JoinPoint joinPoint) throws Throwable {
            // do some stuff
            Object result = joinPoint.proceed();
            // do some other stuff
            return result;
        }

        /**
         * @Around("call(* com.mypackage.Target.*(..))")
         */
        public Object advice2(final JoinPoint joinPoint) throws Throwable {
            // do some stuff
            Object result = joinPoint.proceed();
            // do some other stuff
            return result;
        }

        /**
         * @Mixin("within(com.mypackage..*)")
         */
        public static class MyIntroduction extends SuperMixin implements ContractualInterface {
            ... // introduced methods and fields
        }
    }

### Introduction definition

In the aspect class you specify the introduction to add as field for interface introduction (marker interface with no required method) or as public inner-class for mixins.

Interface introduction are added by adding a field to the aspect. The field type has to be the interface that you want to introduce. The `@Introduce` annotation is then used to specify the pattern matching the classes you want to apply the interface to. For details see the Introductions section.

Interface introduction with implementation, also known as mixins, are added by adding a public static inner-class to the aspect class. For details see the Introductions section.

## Pointcuts

The `Pointcut` class implements the pointcut concept. A Pointcut picks out join points, i.e. selects well-defined points in the program flow.

This section describes how to define named pointcuts using annotations, for a detailed description on how pointcuts are written and composed see the Pointcut definition and Pointcut composition sections.

Named pointcuts are defined as fields in the Aspect class, or as method if they have a signature (that is using the `args()` selector), and they have to follow the following requirements:

1. If defined as a field, the field is of type `org.codehaus.aspectwerkz.definition.Pointcut` and should be declared in the aspect class or hierarchy.
2. The `@Expression` annotation allows us to define the type and pattern of the pointcut. There can be a composition, whether or not anonymous like in `@Expression("anExpression OR call(<call pattern>)")`
3. If using the `args()` selector, the pointcut is defined as a method. The return type of the method does not matter, but the signature must conform to the `args()` selector (see samples below).
4. The name of the pointcut must be unique - that is its signature does not allow to differenciate to pointcut defined as method. The methods names must differ.

The name of the pointcut is the field name if a field, or the method name if a method.

Java 5 annotations

        //-- defined as fields

        @Expression("execution(* com.package..*.*(..))")
        Poincut allMethods;

        @Expression("set(* com.package.Constants.*)")
        Pointcut allConstantAccess;

        //-- defined as methods

        @Expression("execution(* com.package..*.*(..)) && args(s)")
        Poincut allMethodsWithStringArg(String s) {return null;}

        @Expression("execution(* com.package..*.*(..)) && args(i, s, String ..)")
        void allMethodsWithIntArgTwoStringArgsAndSomeOtherArgs(int i, String s) {}

JavaDoc annotations

        //-- defined as fields

        /**
         * @Expression("execution(* com.package..*.*(..))")
         */
        Poincut allMethods;

        /**
         * @Expression("set(* com.package.Constants.*)")
         */
        Pointcut allConstantAccess;

        //-- defined as methods

        /**
         * @Expression("execution(* com.package..*.*(..)) && args(s)")
         */
        Poincut allMethodsWithStringArg(String s) {return null;}

        /**
         * @Expression("execution(* com.package..*.*(..)) && args(i, s, String ..)")
         */
        void allMethodsWithIntArgTwoStringArgsAndSomeOtherArgs(int i, String s) {}

## Advice

The advice are implemented as regular methods in the Aspect class with the following requirements:

1. The signature of the method is `public Object <name of method>(JoinPoint joinPoint) throws Throwable` (the public modifier is not mandatory, choose according to your needs) unless...

- The advice is bounded to a pointcut with signature ( `args()`). In such a case, the parameter referenced in the pointcut signature must appear in the advice signature. The JoinPoint parameter must appear although not referenced by the pointcut signature. We can thus have any signature.
- The method has a metadata that specifies the advice type and the matching joinpoints through a pointcut expression. The matching joinpoints are whether defined as an anonymous pointcut (and not a as a field) whether as an algebraic expression composed by other poincuts, whose type matches the advice type.
  If the expression is referencing a pointcut with a signature, then the parameters names as defined in the method signature must be passed to it.

The supported types of advice are the following.

- `@Around <poincut expression>` - is invoked "around" the join point. Can be used to intercept method invocations on the 'callee' side.
- `@Before <poincut expression>` - is invoked before the join point. Can be used for advising fields or method invocations on the 'caller' side.
- `@After <poincut expression>` - is invoked after the join point. Can be used for advising fields or method invocations on the 'caller' side.
- `@AfterFinally <poincut expression>` - same as @After (invoked after the join point).
  See details.
- `@AfterReturning <poincut expression>` - is invoked after a method normal return (no exception thrown)
  See details.
- `@AfterThrowing <poincut expression>` - is invoked after a method return with an exception.
  See details.

Both anonymous pointcut expressions and expressions made out of named pointcuts are supported. See example below.

Here is a simple example of an `Around` advice using Java 5 annotation style, the definition would be the same using JavaDoc annotations. (For more examples see the Examples section.)

Java 5 annotations

        //-- no arguments, JoinPoint is implictly mandatory

        /**
         * Non-anonymous expression (pc1 and pc2 are fields of type Pointcut with metadata).
         */
        @Around("pc1 && pc2")
        public Object myAroundAdvice1(StaticJoinPoint joinPoint) throws Throwable {
            // do some stuff
            Object result = joinPoint.proceed();
            // do some more stuff
            return result;
        }

        /**
         * Anonymous pointcuts.
         */
        @Around("execution(* com.package.Target.*(..)) || call(* com.package.Target.*(..))")
        public Object myAroundAdvice2(StaticJoinPoint joinPoint) throws Throwable {
            // do some stuff
            Object result = joinPoint.proceed();
            // do some more stuff
            return result;
        }

        //-- pointcut with signatures

        /**
         * Non-anonymous expression (pc1 is a method defining a Pointcut, with a String parameter).
         * Note the use of "s" in the metadata expression.
         */
        @Around("pc1(s)")
        public Object myAroundAdvice1WithArg(StaticJoinPoint joinPoint, String s) throws Throwable {
            // do some stuff
            // "s" can be accessed without the use of RTTI
            // Note that it can be modified according to the rules of Java Language references passing
            System.out.println(s);
            Object result = joinPoint.proceed();
            // do some more stuff
            return result;
        }

        /**
         * Anonymous pointcuts.
         */
        @Around("execution(* com.package.Target.*(..)) && args(arg0, int[][], arg2)")
        public Object myAroundAdvice2WithArg(StaticJoinPoint joinPoint, String arg0, com.Foo arg2) throws Throwable {
            // do some stuff
            // access arg0, arg2
            arg2.doSomething();
            Object result = joinPoint.proceed();
            // do some more stuff
            return result;
        }

## Introductions

`AspectWerkz` supports two types of introductions

- Mixins - are separated from the aspect concept. They can be declared within an or outside of an aspect
- Interface introductions - can only be declared within an aspect

Using annotations, introductions are defined as:

- Fields of the aspect class whose type is the interface to introduce.
  Use interface introductions only if the interface does not require any implementation (marker interface).
  Fields are marked with the annotation `@Introduce <pointcut>`, where pointcut is composed with within, hasfield, hasmethod.
- Public inner class of the aspect class.
  The inner class declares to implement the interface(s) to introduce and effectively implements it. The inner class is marked with the annotation `@Mixin <pointcut>`, where pointcut is composed with within, hasField, hasMethod.

### Interface introductions

Interface introductions (introduction of marker interfaces) are defined as fields in the aspect class. The type of the field is the interface to introduce.
The field is marked with the annotation `@Introduce <pointcut>` to specify to which classes the introduction applies.
The introduction type is the field type.

When using abstract aspects or aspect inheritance, the aspect's super class can define interface introductions without specifying a `@Introduce <pointcut>` metadata. The concrete aspect should thus override the fields and specify the metadata defining to which classes the introduction applies.

Java 5 annotations

        @Introduce("within(com.package.*)")
        protected Serializable introduction1;

        @Introduce("within(com.package.*)")
        public OtherMarkerInterface introduction2;

JavaDoc annotations

        /**
         * @Introduce("within(com.package.*)")
         */
        protected Serializable introduction1;

        /**
         * @Introduce("within(com.package.*)")
         */
        public OtherMarkerInterface introduction2;

### Mixins

For details on the mixin implementation and definition see this section.

## Annotation reference

This section references all annotations used in the annotation definition.

Annotations | level | defines | anonymous value | parameter(s)
--- | --- | --- | --- | ---
[O:defaultValue] for optional parameter with default value
@Aspect | class | Aspect | perJVM | perClass | perInstance [O:perJVM] | name=[0:<aspect class name>]
@Expression | Pointcut field, method with matching signature | Pointcut, method execution | <pointcut expression> |
@Introduce | field | Interface Introduction | <within/hasfield/hasmethod pointcut (and composition of those)> |
@Mixin | class or inner class | Mixin | <within/hasxxx pointcut> | deploymentModel=(perJVM | perClass | perInstance [O:perInstance]), isTransient=(true | false [O:false])
@Around | method | around advice | <pointcut expression> |
@Before | method | before advice | <pointcut expression> |
@After | method | after finally advice | <pointcut expression> |
@AfterFinally | method | after finally advice | <pointcut expression> |
@AfterReturning | method | after returning advice | <pointcut expression> | the FQN of the return type (optional)
@AfterThrowing | method | after throwing advice | <pointcut expression> | the FQN of the exception type (optional)
@<name> | any | custom annotation (typed or untyped) |  |

## Aspect annotation compilation

JavaDoc annotation defined aspects have to be post-compiled to incorporate the metadata into the class file bytecode. This post-compilation step will not be needed with Java 5 annotation defined aspects. For now you need to first compile the aspect classes with javac compiler and then post compile the `.class` files with the aspect source code as input.

To post-compile the aspect's `.class` files you have to use the `AnnotationC` compiler, which needs both the regular `.class` files and the aspect sources files containing the annotation metadata. You can run the `AnnotationC` from the command line. (It might be useful to run the `ASPECTWERKZ_HOME/bin/setEnv.{bat|sh}` script first.)

    java [options...] org.codehaus.aspectwerkz.annotation.AnnotationC
        -src <path to src dirs>
        -srcpath <list of files>
        -srcincludes <path to file>
        -dest <path to destination dir>
        -custom <property file for cutom annotations>
        -verbose

Description of compiler options

Note: only one of `-src`, `-srcpath` and `-srcincludes` may be used.

- `-verbose` - (optional) activates compilation status information
- `-src <path to src dirs>` - provides the list of source directories separated by File.pathSeparator
- `-srcpath <list of files>` - provides a comma separated list of source files
- `-srcincludes <path to file>` - provides the path to a file containing the list of source files (one name per line)
- `-dest <path to destination dir>` - (optional) if omitted the compiled classes will be written to the initial directory
- `-custom <property file for cutom annotations>` - (optional) only needed if you have custom annotations you want to compile

`AnnotationC` can also be used to handle custom annotations as described here.

Note that if you are using the `-dest` option, the anonymous inner classes will not be copied to the destination directory, since the anonymous classes are not taken into account by the Annotation compiler. In such a case it is recommanded to add the following (if using Ant) just after the call to AnnotationC when the `-dest` option is used: (adapt according to the directories you are using)
<copy todir="classes/annotated" overwrite="false"> <fileset dir="classes/regular"/> </copy>

### AnnotationC Ant task

We also have an Ant task for the AnnotationC compiler.

For details see this this section.

## XML deployment descriptor

The deployment descriptor is needed for the runtime system to know which aspects it should load. It always has to be specified even though all definition is made in annotations.

Example:

    <aspectwerkz>
        <system id="tests">
            <package name="foo.bar">
                <aspect class="MyAspect1"/>
                <aspect class="MyAspect2"/>
                ...
            </package>
        </system>
    </aspectwerkz>