Introducing AspectJ


AspectJ was the first implementation of the AOP paradigm to come out of the research work undertaken at Xerox PARC and is the most mature and complete AOP implementation currently available. The Xerox team, led by Gregor Kiczales, produced AspectJ both as a first cut at a language specification for AOP and an AOP implementation. The Xerox AspectJ team chose to extend the Java language to support aspect-oriented concepts in addition to developing compilation and debugging tools for their new Java variant.

AspectJ represents a language-based AOP implementation, bringing new constructs and semantics to Java with additional keywords. These additions turn Java from a single-paradigm to a multiparadigm language, able to exploit the benefits of both OOP and AOP. Historically, this approach follows the same route as taken by C++, which extended the C programming language to incorporate OOP constructs.

When AspectJ reached a level of stability, it was relocated from the research labs of Xerox PARC into the arms of the open source community. AspectJ is now maintained as an Eclipse Technology project and can be found at http://eclipse.org/aspectj.

AspectJ and Eclipse

The Eclipse platform is a generic development environment that offers a powerful collection of Java development tools (JDT), including a Java source editor, compiler, and debugger.

Chapter 13 describes the Eclipse platform and the JDT in detail.


AspectJ builds on the services of the JDT to provide the AspectJ Development Tool (AJDT), a fully featured Eclipse plug-in that brings the capabilities of the Eclipse platform to the AspectJ language, including content assist on keywords, aspect browsing, compilation error tracing, and the debugging of aspects.

Despite its links with Eclipse, AspectJ is not bound to the Eclipse platform. The primary focus of the project is the AspectJ compiler, which is available as a standalone executable. As a standalone release, independent of the AJDT, AspectJ supports the compilation and execution of applications. A structure browser is also available for interrogating AOP constructs within the code.

AspectJ also integrates with other popular development environments, with plug-ins available for JBuilder, NetBeans, and Emacs. Refer to the AspectJ site for information on where to obtain these and other plug-ins.

The AspectJ Compiler

AspectJ supports compile-time weaving, with version 1.1.2 offering limited support for load-time weaving.

The AspectJ compiler builds on the capabilities of Eclipse's Java compiler, thereby firmly tying the language to the open source community and cutting its initial ties with javac. The Eclipse compiler is highly sophisticated and offers capabilities such as incremental compilation. By using the Eclipse compiler as its base, AspectJ leverages these capabilities for its own builds. Classes produced by the AspectJ compiler run on any Java-compatible platform.

AspectJ Example

To understand how some of the fundamental concepts of AOP are applied, let's look at an example built using AspectJ. The example covers the main concepts of AOP and introduces the new language constructs AspectJ adds to the Java language to support AOP.

The code for the example adds aspects to an imaginary stock-control system. Stock items are contained within a central warehouse, and the stock-control system is responsible for managing all stock going into the warehouse. A single class encapsulates warehouse functionality. Listing 11-1 shows the implementation of the Warehouse class.

Listing 11-1. The Warehouse Class
 package stock; import java.util.ArrayList; /**  * Warehouse class for storing stock items.  */ public class Warehouse {   private ArrayList stockItems;   public Warehouse() {     stockItems = new ArrayList();   }   /**    * Add a new stock item    */   public void add(String stockItem) {     stockItems.add(stockItem);   }   /**    * Return the number of items in stock    */   public int itemsInStock() {     return stockItems.size();   } } 

The warehouse is nothing more than a wrapper around an ArrayList. However, the intention of the code is to demonstrate the concepts of AOP, not to build a fully featured stock-control system.

Our rudimentary stock-control system adds a number of stock items to the warehouse. Listing 11-2 shows the code for the stock-control example.

Listing 11-2. The Main StockControl Class
 package stock; /**  * Adds stock items to the warehouse  */ public class StockControl {   public void processStockItems() {     //  Create the warehouse     //     Warehouse warehouse = new Warehouse();     // Add some stock     //     warehouse.add("Washing Machine");     warehouse.add("Microwave Oven");     warehouse.add("Television");   }   public static void main(String[] args) {     StockControl stockCtrl = new StockControl();     stockCtrl.processStockItems();   } } 

The example application is very simple, but it is easy to imagine a production version on a much grander scale. The concept of encapsulating the warehouse functionality into a component accessed via a common interface from all parts of the system is a design in keeping with object-oriented architecture.

To illustrate how AOP weaves in functionality, we introduce an auditing (or logging) concern into the system. The following use case defines the new auditing requirements:

  1. All stock items must have an audit-log entry before going into the warehouse.

  2. After adding a stock item to the warehouse, the number of items in the warehouse must be written to the audit log.

To incorporate the new requirements into the system using AOP, the first task is to specify the join points in the program where the auditing concern crosscuts the main concern. Achieving this task requires the declaration of a pointcut designator.

A pointcut designator is a special AOP language construct that specifies join point collections and precisely defines where a crosscutting concern intersects the main concern. AspectJ supports the declaration of pointcuts at a number of different locations in a program's execution:

  • Method and constructor call

  • Method and constructor reception

  • Method and constructor execution

  • Field access

  • Exception handler execution

  • Class and object initialization

Complying with the auditing requirements requires the declaration of a pointcut occurring at the point of the call to the add() method on the Warehouse class. We need to weave in the auditing advice ahead of the add() method's invocation and upon returning from the call.

Listing 11-3 shows the code for the aspect that specifies the pointcut declaration and the advice for weaving into the system.

Listing 11-3. Auditing Aspect AuditingAspect.java
 package stock; import org.aspectj.lang.reflect.SourceLocation; /**  * Aspect to add auditing to the stock control system.  */ public aspect AuditingAspect {   // Pointcut declaration   //   pointcut auditStockItem() : call(* Warehouse.add(..));   // Advice to execute before call   //   before() : auditStockItem() {     System.out.println("<--Audit log entry start-->");     // Log the name of the calling class     //     SourceLocation sl = thisJoinPoint.getSourceLocation();     Class myClass = (Class)sl.getWithinType();     System.out.println("\tCaller: " + myClass.toString());     // Log the stock item description     //     Object[] args = thisJoinPoint.getArgs();     for(int i=0; i < args.length; ++i) {       System.out.println("\tAdding item: " + args[i]);     }   }   // Advice to execute after call   //   after() : auditStockItem() {     Warehouse warehouse;     warehouse = (Warehouse) thisJoinPoint.getTarget();     System.out.println("\tItems in stock: " +                         warehouse.itemsInStock());     System.out.println("<--Audit log entry end-->");   } } 

Examining the code in Listing 11-3 reveals a number of syntactic differences from standard Java, with the AOP keywords shown in bold text. The AspectJ keyword aspect specifies that we are defining an aspect and not a Java class. AspectJ uses aspects as a unit of modularization for crosscutting concerns. Aspects are similar to classes in that they have a type and can extend classes and other aspects. The main difference between the two constructs is that aspects cannot be instantiated with the new operator. They are also not directly interchangeable with classes.

The keyword pointcut declares the pointcut designator for the auditing advice and assigns the pointcut the name of auditStockItem(). Here is the full declaration of the pointcut:

 pointcut auditStockItem() : call(* Warehouse.add(..)); 

The syntax following the pointcut name is of greatest interest because this captures the join points for the auditing concern. It is defined as call(* Warehouse.add(..), where call specifies the join point as the point at which the method is invoked. The remainder of the pointcut designator specifies the method signature for matching the join point at runtime. From the example, a match will be found for all add() methods on instances of the Warehouse class, regardless of access, return type, or arguments. AspectJ provides a rich syntax for defining join points, enabling the definition of sophisticated matches that go well beyond the simple example shown.

Having identified the join points in the program, the next step is to provide the auditing advice AspectJ will weave into the main concern. AspectJ has three options for associating advice with a join point: before(), after(), or around() the join point.

Our auditing advice has to both precede and follow the call to the Warehouse instance. The AspectJ syntax of before() and after() details precisely where the advice is to be injected once the join point is reached. This syntax gives the following method signatures for the auditing advice:

 before() : auditStockItem() {   ... after() : auditStockItem() {   ... 

Examining the code for the before and after advice highlights the use of the thisJoinPoint object, which provides a context for the join point and makes information relating to the join point available to the advice. The example uses this information to log the name of the calling class and the arguments to the Warehouse.add() method, and to invoke the itemsInStock() method on the Warehouse instance.

The code for the example was compiled and run on the Eclipse platform using the Eclipse AJDT plug-in. The use of an aspect-aware development environment offers significant benefits over a plain code editor and build script. In addition to syntax coloring of keywords and content-assist on AspectJ types, aspect-aware environments, such as AJDT for Eclipse, provide a visual cue to where join points occur within the application. This is an invaluable aid for determining the impact of a pointcut declaration upon the code of the core concerns.

Figure 11-1 depicts this feature of the AJDT, which shows the code from the example open as a project on the Eclipse platform.

Figure 11-1. The Eclipse platform with an AspectJ project open.


The upper right pane shows the code for the StockControl class open in an aspect-aware editor. Marks on the left border of the editor denote where the join points of the AuditingAspect aspect crosscut the StockControl concerns. The content of the outline view, seen in the lower left pane, displays a hierarchical view of the location of the aspect's injected advice. The lower right pane contains the console view, which shows the results of executing the program.

The example contains only a single class and aspect. However, in a larger system with thousands of files, the pointcut declaration is just as easily applied across all classes within the system. This ability to inject functionality directly into a large system and with a high degree of precision makes AOP an ideal candidate for a rapid development language. Moreover, the dynamic nature of the language makes it an ideal prototyping tool because new behavior is easily added or removed as system functionality is explored.

Tip

AOP is potentially well suited to the development of evolutionary prototypes. Omitting concerns such as security, auditing, logging, and persistence, enables a prototype to be rapidly constructed using a conventional OOP approach. Once the prototype is accepted, aspects weave in these concerns to transform the prototype into a production-standard application.


AspectJ was the first release of an AOP language and still stands out as the most comprehensive AOP implementation available, offering unrivaled tool support in the form of the AJDT for Eclipse. Since its emergence from the research labs of Xerox PARC, a host of alternative AOP implementations has joined AspectJ. These newcomers to the AOP paradigm take a different approach to AspectJ. Instead of a new language, they provide a framework for defining aspects. The next section discusses this approach.



    Rapid J2EE Development. An Adaptive Foundation for Enterprise Applications
    Rapid J2EEв„ў Development: An Adaptive Foundation for Enterprise Applications
    ISBN: 0131472208
    EAN: 2147483647
    Year: 2005
    Pages: 159
    Authors: Alan Monnox

    flylib.com © 2008-2017.
    If you may any questions please contact us: flylib@qtcs.net