Introduction

Aspect-oriented programming helps programmers in the separation of (cross-cutting) concerns to improve the overall architecture of an application by making it more modular and removing duplicate code.

Archive for the ‘AOP’ Category

Saturday, May 8th, 2004

AOP: Passing Context

One thing I haven’t talked about yet is passing context from a join point to an advice. An advice often needs certain information about the join point. For example the arguments passed to the join point, the class the join point is declared in and so on. All this information is called context. There do exist special pointcuts to capture these context. ApsectJ provides the following: this(), target() and args(). Let’s directly step into it:

We have a package called org.swacker.geom. In this package are by now two classes, Rectangle and Circle. These two classes implement the interface Shape. This interface declares one method: fill(newColor:Color). What we want to do is logging the calls to any class implementing this interface and printing out the name of this class as well as the new color the shape shall be filled with. Our final ouput shall look like this:

  1. About to fill a ‘org.swacker.geom.Rectangle’ instance with the color ‘#000000′.

To achieve this we somehow must get down to the target of the call as well as the arguments passed to the method. What we need is the target() and args() pointcut. We have everything we need now. Thus let’s start coding:

  1. public aspect ShapeAspect {
  2.   before(Shape shape, Color color) :
  3.       call(void Shape+.fill(Color))
  4.       && target(shape)
  5.       && args(color) {
  6.     System.out.println("About to fill a ‘" + shape.getClass().getName() + "’ instance with the color ‘" + color + "’.");
  7.   }
  8. }

We’ll now walk through this step by step.
We have an advice specification: before(Shape shape, Color color). It’s a before advice that collects some context. An instance of type Shape and another of type Color. What we also have are three pointcuts that are connected by && operators. We firstly capture all calls to the method fill() that is implemented in the class Shape or any of its subclass: call(void Shape+.fill(Color)).
Then we say that the target of the call shall be mapped to the context named shape in the advice specification: target(shape).
What we also do is taking the first argument of the method call and say that it shall me mapped to the context named color. This mapping will now be done automatically and we can use the context to build our output: System.out.println(”About to fill a ‘” + shape.getClass().getName() + “‘ instance with the color ‘” + color + “‘.”);.

When we now write a little test which body looks similar to this:

  1. Rectangle r = new Rectangle();
  2. r.fill(new Color(#000000));
  3. Circle c = new Circle();
  4. c.fill(new Color(#0000FF));

and compile the whole thing together with the aspect ShapeAspect we will get the following output:

  1. About to fill a ‘org.swacker.geom.Rectangle’ instance with the color ‘#000000′.
  2. About to fill a ‘org.swacker.geom.Circle’ instance with the color ‘#0000FF’.
Thursday, May 6th, 2004

AOP: Advice

As I already said, an advice is the code to be executed at a join point that has been selected by a pointcut. There exist three types of advices: the before, after and around advice. The before advice executes before the execution of a join point, the after advice after the execution of a join point and the around advice surrounds the join point’s execution. We will now look at each advice in turn.

Before advice:

  • Structure:
    before() : <Pointcut> {

    }
  • Example:
    before() : call(* MyClass.myMethod()) {
    System.out.println(”about to execute MyClass.myMethod()”);
    }

After advice:

  • Structure:
    after() : <Pointcut> {

    }

    after() returning(<ReturnType returnObject>) : <Pointcut> {

    }

    after() throwing(<ExceptionType exceptionObject>) : <Pointcut> {

    }

  • Example:
    after() : call(* MyClass.myMethod()) {
    System.out.println(”executed MyClass.myMethod()”);
    }

    after() returning(int result) : call(* int MyClass.myMethod()) {
    System.out.println(”The method MyClass.myMethod() returned ” + result);
    }

    after() throwing(Exception e) : call(* int MyClass.myMethod() throws Exception) {
    System.out.println(”The method MyClass.myMethod() threw the exception ” + e);
    }

  • Explanation:
    As you can see is it also possible to capture the result of a method call or the exception the method threw. You can deal with these the same way you do with normal arguments/parameters.

Around advice:

  • Explanation:
    The before and after advice are quite simple. But the around advice will need a little more explanation.
    If you do not explicitly call the method proceed() in the around advice the originally called method won’t be executed. The method will then just be bypassed. When calling proceed() you must pass the same number and types of arguments as collected by the advice. The proceed() method will also return the result of the method call.
    Another thing you have to do is specifying the return type the adviced join point has. If you are not sure what the return type of the join point is because you capture multiple different join points independent of their return type use Object. AspectJ will then automatically adjust the type based on the return type of the particular join point.
  • Structure:
    <returnType> around() : <Pointcut> {

    }
  • Example:
    int around() : call(* int MyClass.myMethod()) {
    // doSomething
    int result = proceed(); //
    // doAnotherThing
    return result;
    }
Tuesday, May 4th, 2004

AOP: Lexical-Structure Based Pointcuts

You can capture join points based on their lexical structure, that means on the scope of the code as it was written. There do exist two lexical-structure pointcuts: within(Type) and withincode(Method-/ConstructorSignature). I’ll explain how the function with the help of two examples:

within(MyClass+)
This would capture all join points inside the lexical scope of the class MyClass and all its subclasses.

withincode(* MyClass.myMethod(..))
This would capture all join points inside the lexical scope of any myMethod() method of the class MyClass.

I have used wildcards in the examples to make the explanation simpler. Refer to the article AOP: Wildcards if you do not understand what ‘*’, ‘+’ or ‘..’ mean.

You probably wonder why one would need lexical-scope based pointcuts. The answer is quite simple. When you capture calls to methods like System.out.println() that are probably also used within the aspect itself you must exclude this calls to avoid recursion.

Example:
call (* System.out.println(..)) && !within(MyAspect)
This pointcut will capture all calls to the System.out.println() method excluding the calls from within the aspect MyAspect.

I won’t write any more articles on pointcuts. But there do also exist pointcuts to capture the execution object and the arguments as well as conditional check pointcuts. I have found a comprehensive article on http://dev.eclipse.org called Pointcuts. Just refer to this article to learn about everything you have to know about pointcuts.

Tuesday, May 4th, 2004

AOP: Control-Flow Based Pointcuts

If you wanna catch join points that occur within the control flow of another join point you need control-flow based pointcuts. There do only exist two control-flow based pointcuts: cflow(Pointcut) and cflowbelow(Pointcut). The cflow(Pointcut) pointcut will capture all joint points that occur within the specified pointcut, including the join points matching the pointcut itself. Whereas the cflowbelow(Pointcut) pointcut will only capture the join points that occur within the join points matching the specified pointcut.

Example:
cflow(call(* MyClass.myMethod(..))
This pointcut would capture all join points that occur inside any myMethod() method in MyClass that is called, including the call to myMethod() itself.

cflowbelow(call(* MyClass.myMethod(..))
If you’d change cflow to cflowbelow the call to myMethod() would not be captured.

Tuesday, May 4th, 2004

AOP: Spring Framework

I have recently been playing around with a layered Jave/J2EE framework called Spring. I came over a package called ‘aop’. That package really drew my attention on it. Thus I looked into a few classes that seemed to be the core one’s. It seems that they have built an AOP framework based on an open source project called AOP Alliance that provides the basic AOP constructs without the need of a special AOP language like AspectJ. They have done it using the Reflection API Java provides.
Given a similar API in Flash it would probably be possible to create a similar AOP framework for it. But that’s something I’m presently just dreaming about.
They have written a ‘little’ chapter on the aop framework called: Aspect Oriented Programming with Spring. I’d suggest you to refer to this article if you wanna learn more about it.