The first paper to use the term aspect-oriented programming (AOP) was published in 1997 by a research group at the Palo Alto Research Center (PARC **). (1) Since that time, interest in aspect-oriented programming has steadily grown to the point that it now attracts large audiences at developer conferences, and a growing number of companies are using AOP to build production applications. In this paper we first introduce AOP and the benefits it brings and then look at the AOP language Aspect J **. (2) AspectJ is an open-source project initiated by PARC and now led by IBM. The AspectJ Development Tools (AJDT) project (3) is a related open-source project, also led by IBM, that provides IDE (integrated development environment) support for programming with AspectJ within the Eclipse IDE. (4) After introducing the language and tools, we discuss the adoption of AspectJ within IBM. The paper concludes by considering the role that open source has played both in the development of AspectJ and AJDT and in IBM's involvement in that process.
WHAT IS AOP?
AOP is a term used to describe a programming technique and a way of thinking about the construction of software applications that complements the forms of expression found in object-oriented programming. The goal of AOP is to improve the modularity of software applications, making them easier to develop, test, and maintain. Aspect-oriented programs comprise of a mixture of objects and aspects. Both encapsulate state and behavior, but whereas the behavior in an object is executed only when explicit calls are made to the object's methods, the behavior in an aspect can also execute at points in the runtime of the program determined by the aspect's specification.
This simple idea turns out to be enormously powerful at modularizing the implementation of certain types of application features and functions. For example, given the requirement to issue a change notification to any registered listeners when the state of any one of a set of model objects changes, an object-based implementation requires the addition of a call to notifyListeners( ) (or some similar method) after each state-changing operation. An aspect-based implementation can simply code (in one module known as an aspect) the following, "After the state of any model object changes, call notifyListeners( )." As another example, consider the use of a persistence service that requires all updates to the persistent state of an application to occur within the scope of a session or transaction. An object-based implementation requires the insertion of logic to start a session before every interaction with the persistence service and to close it again afterwards--managing any exceptions that may be generated by the service along the way. An illustration of this example using the Hibernate (5) persistence framework for session and transaction management is shown in the following listing:
try {
Session session = sessionFactory.openSession( );
Transaction tx = null;
try {
tx = session.beginTransaction( );
//perform updates to persistent state
//here ...
tx.commit( );
} catch (HibernateException hEx) {
if (tx !=null) tx.rollback( );
throw hEx;
} finally {
session.dose( );
}
} catch (HibernateException hEx) {
//handle exception
}
An aspect-based implementation of the same requirement can be coded once in an encapsulated module, "Before updating the persistent state of the application start a session, and after the update has been completed, close it again." Although the application may involve many interactions with the persistence service, the aspect-based implementation will need to be written only once.
Both the change notification and session-management requirements are examples of what the AOP community has termed a crosscutting concern. A crosscutting concern is a single concern in the design or implementation of a system that impacts multiple places in the static structure of the system or in its runtime control flow. Aspects modularize crosscutting concerns, allowing the implementation of a single (crosscutting) concern in a single module, and therefore eliminating violations of the DRY (don't repeat yourself) principle. (6) Instead of the same fragment of code being repeated in many places throughout the application (e.g., the calls to notifyListeners( ), or the session-management logic), the code can be written once in an aspect. This makes the implementation easier to add, remove, and maintain. In the aspect-oriented community the term scattering is often used to describe the situation where multiple fragments of code that all do the same thing (or that do closely related things) are spread throughout a code base in a non-modular fashion.
A concept closely related to scattering is tangling. Tangling occurs when a module (typically a class in an object-oriented system) contains logic pertaining to more than one feature or function. The implementations of the different features are said to be tangled together in the module. As an example, consider the implementation of a BankAccount class that contains logic to place a message in a queue whenever a withdrawal over a certain threshold is made. The implementations of the BankAccount feature and a portion of a SupervisorAlerts feature have become tangled in a single class. By using an aspect to modularize the implementation of the SupervisorAlerts feature, this tangling can be eliminated.
Tangling is an indication of a less than ideal system modularity. In particular, tangling makes it harder to test, maintain, and reuse the tangled feature implementations. Karl Lieberherr recently formulated an update to the Law of Demeter designed to eliminate tangling in a design: "Speak only to your friends that share your current concerns." (7)
By eliminating the effects of scattering and tangling that are prevalent in object-oriented systems, the goal of AOP can be stated simply: "Every module in the system should do one thing and one thing only."
The usual software engineering criteria for what makes a good module (coupling, cohesion, etc.) apply equally to AOP and to object-oriented programming.
Underpinning all AOP systems is something called a join point model. Join points are events that occur during the runtime execution of a program (for example, the initialization of a class, the execution of a method, the handling of an exception, or the updating of a field). The join point model determines which of these events are exposed to the aspect-oriented programmer. Pointcuts are predicates that match join points. For example, all AOP systems known to the authors will provide for a pointcut that matches the execution of a given method (or set of methods). Blocks of code known as advice are written to execute at any join point matched by a pointcut expression associated with the advice.
To implement the change notification requirement that we introduced at the start of this section, an aspect-oriented programmer would write a pointcut that matched join points representing the setting of a field value within any of the model objects. The programmer would then write a simple piece of advice associated with that pointcut to call the notifyhisteners( ) method.
ASPECTJ AND AJDT
In the following section we provide a brief introduction to AspectJ and the AJDT and show how the ideas of aspect orientation are implemented in the AspectJ language and supported by AJDT.
AspectJ
The AspectJ language is an extension of the Java** language that supports AOP. The programs generated by the AspectJ compiler can run on any Java Virtual Machine (JVM **) and have no special runtime requirements, other than that the small AspectJ runtime library, aspectjrt.jar, be available somewhere on the classpath (a listing of locations where Java can find class files).
The declaration of an aspect in AspectJ looks very much like a class declaration, except that the keyword class is replaced by the keyword aspect:
public aspect SupervisorAlerts {
...
}
Aspects can have state (fields) and behavior encapsulated in methods in just the same way as a class:
public aspect SupervisorAlerts {
private static final Money
WITHDRAWAL_THRESHOLD = new Money(1000, 0);
private QueueConnectionFactory
connectionFactory;
...
private void sendMessage(String messageText) {
...
}
}
AspectJ's join point model includes join points for:
* A method or constructor call
* The execution of a method or constructor
* The accessing or updating of a field
* The handling of an exception
* The initialization of a class or object
* The execution of advice
Pointcuts in AspectJ are declared using the pointcut keyword. To issue a supervisor alert whenever a withdrawal is made over some threshold, a pointcut called withdrawl( ) that will match a join point representing the execution of a withdrawal method can be defined:
<