AspectJ In Action: Enterprise AOP with Spring Applications by Ramnivas Laddad
I came across aspect oriented programming around 2002 when the development manager at the company where I was working asked me to do a talk on the subject. At the time, the main exponent of this technology was the AspectJ compiler that had been developed by Gregor Kiczales, who we respected as one of the main designers of the object system that was included in the Common Lisp specification.
This book shows just how far this technology has come over the years and how well it is supported by Spring, one of the large Java application frameworks.
Aspects are a means of dealing with many of the cross-cutting concerns that can be found in object oriented applications. A program in an object oriented language chooses one of the many possible decompositions of a problem into groups of inheritance related classes… this always leaves related functionality (think tracing or security) that is scattered across the classes with no easy way of modularising this functionality. Interfaces give a way of relating non-inheritance related parts of the main inheritance tree, but the single inheritance found in Java and C# doesn’t allow these interfaces to take state into the related items. Aspect oriented programming allows mixins which step over this problem while enabling so much more.
The book introduces AOP (aspect oriented programming) via AspectJ and its syntax extensions to standard Java. From the dynamic point of view, pointcuts identify collections of join points which can have advice added to them in the form of code which is executed before, after (either always or on value return or if the method exits via an exception) or around the existing code. In the latter case, the user code uses the new keyword proceed() to cause execution of the original code, or alternatively can call proceed(…) modifying the arguments that the original code runs on (though with the limitation that the matching method cannot be changed).
For example, we could modify the program to print a message before any of the deliver methods in the MessageCommunicator class are executed, by using the following:
pointcut secureAccess() : execution(* MessageComminicator.deliver(..));
before() : secureAcess()
The AspectJ syntax allows a lot of flexibility in the selection of the join points. We can, for example, select by method name, arguments, return type, annotation and which type the method is owned by. Moreover, one can test for method invocations happening inside other join points and even capture the arguments so that they can be used inside the added advice. There are also facilities for reflection over the join point inside the advice. As well as allowing dynamic modification, the system also allows the static structure of the program to be changed (at compile time). Interfaces and annotations can be added to existing classes, and instances of standard classes and aspects can be associated in several ways – aspects can be associated per type, per object or per control flow, and default to having a singleton instance of the aspect in the system. Moreover, there is a means to raise errors and warning if particular point cuts are empty or non-empty.
In order to make adoption easier, AspectJ has a second version of its syntax which uses Java Annotations instead of syntax extensions. This means that programs can be compiled using a standard java compiler, though with the downside of throwing away some of the potential error checking.
The book goes into some detail about how aspects are woven into the existing code to produce the final program. This weaving can happen at compile time, as a post compile action or as a load time step, or even, in the case of Spring, by using proxy objects instead of the real objects and adding the advice as decorators called by the proxy. In this last case, no special compilation is needed, but the proxy implementation cannot add advice to calls via the this pointer which will always end up unproxied. The book goes into details about the advantages of these various implementation strategies, and points to a couple of papers including this one.
There are some really good examples in the book of the use of aspects. Adding change notification functions to properties is one of the classic examples where a lot of boiler plate code typically has to be written which has a standard form which could be made into an aspect. The book shows how easy this pattern is to implement inside an aspect, leaving the original code much easier to read, though you’d really need tool support to understand how the aspects mix into your existing java code. The book emphasises the fact that the aspect can be abstract, allowing parts such as the point cut to be defined in another place closer to where the aspect is used. Aspects can inherit from abstract aspects but not from concrete aspects (though this limitation might go in the future).
There are loads of other good examples in the book, all with great explanations. An aspect that enforces restrictions on the return value such that collection returning methods must return an empty collection instead of null, and an aspect that ensures that code that modifies the GUI runs on the gui thread, together with a related aspect that adds locking to a reader-writer pattern.
The book also introduces a number of new patterns.
The wormhole: The cflow join point is used to transfer values from an invocation higher up the stack to the current advice without needing to pass the data as a parameter or put it into thread local strorage.
The worker: The around advice uses a closure to move the execution of the original code on to another thread.
The Participant pattern: which uses abstract pointcuts whose meaning can be defined nearer to where the aspects are used.
The book finishes by covering transactions and security, which are the standard example of aspects.
The explanations in the book are fantastic and the practical advice is worth every penny.