Aspect Oriented Programming (AOP) is a promising new technology for separating crosscutting concerns that are usually hard to do in object-oriented programming.
Nowadays, object-oriented programming (OOP) has become the mainstream programming paradigm where real world problems are decomposed into objects that abstract behavior and data in a single unit.
OOP encourages software re-use by providing design and language constructs for modularity, encapsulation, inheritance, and polymorphism. Although OOP has met great success in modeling and implementing complex software systems, it has its problems. Practical experience with large projects has shown that programmers may face some problems with maintaining their code because it becomes increasingly difficult to cleanly separate concerns into modules. An attempt to do a minor change in the program design may require several updates to a large number of unrelated modules.
"concern that crosscuts the main purpose of a unit, or that is spanned across multiple units."
Two concerns crosscut each other when their relation implies tangled code.
This figure represents a typical application that is broken down into modules. Each module’s main concern is to provide services for its particular domain. However, each of these modules also requires similar ancillary functionalities, such as security logging and transaction management. An example of crosscutting concerns is "logging," which is frequently used in distributed applications to aid debugging by tracing method calls. Suppose we do logging at both the beginning and the end of each function body. This will result in crosscutting all classes that have at least one function.
The common object-oriented technique for reusing common functionality is through inheritance or delegation. But inheritance can lead to a brittle object hierarchy if the same base class is used throughout an application, and delegation can be cumbersome and still requires duplicated calls to the delegate object.
AOP presents an alternative that can be cleaner in many circumstances. With AOP, you still define the common functionality in one place, but you can declaratively define how and where this functionality is applied without having to modify the class to which you are applying the new feature. Cross-cutting concerns can now be modularized into special objects called aspects. This has two benefits. First, the logic for each concern is now in one place, as opposed to being scattered all over the code base. Second, our service modules are now cleaner since they only contain code for their core functionality and secondary concerns have been moved to aspects.
- Programming paradigm for encapsulating crosscutting concerns.
- AOP builds on top of other programming paradigms: object-oriented, procedural or functional. It does not supplant them.
- Encapsulate crosscutting concerns into aspects.
Aspect: unit encapsulating a crosscutting concern.
- AOP is not about “patching” pieces of code.
- AOP is about performing an action systematically upon recognition of a behavior in the code.
AOP is a new technology for separating crosscutting concerns into single units called aspects. An aspect is a modular unit of crosscutting implementation. It encapsulates behaviors that affect multiple classes into reusable modules. With AOP, we start by implementing our project using our OO language (for example, Java), and then we deal separately with crosscutting concerns in our code by implementing aspects. Finally, both the code and aspects are combined into a final executable form using an aspect weaver. As a result, a single aspect can contribute to the implementation of a number of methods, modules, or objects, increasing both reusability and maintainability of the code. Figure 1 explains the weaving process. You should note that the original code doesn't need to know about any functionality the aspect has added; it needs only to be recompiled without the aspect to regain the original functionality.
Figure 1: Aspect Weaver
In that way, AOP complements object-oriented programming, not replacing it, by facilitating another type of modularity that pulls together the widespread implementation of a crosscutting concern into a single unit. These units are termed aspects, hence the name aspect oriented programming.
Like most technologies, AOP has a jargon unto itself. Unfortunately, many of the terms used to describe AOP features are not intuitive. But they are now part of the AOP language and, in order to understand AOP, you must know this language. In other words, before you walk the walk, you have to learn to talk the talk.
An aspect is the cross-cutting functionality you are implementing. It is the aspect, or area, of your application you are modularizing. The most common (albeit simple) example of an aspect is logging. Logging is something that is required throughout an application. However, because applications tend to be broken down into layers based on functionality, reusing a logging module through inheritance
does not make sense. However, you can create a logging aspect and apply it throughout your application using AOP.
A joinpoint is a candidate point in the execution of the application where an aspect can be plugged in. This point could be a method being called, an exception being thrown, or even a field being modified. These are the points where your aspect’s code can be inserted into the normal flow of your application to add new behavior.
Advice is the actual implementation of our aspect. It is advising your application of new behavior. In our logging example, the logging advice would contain the code that implements the actual logging, such as writing to a log file. Advice is inserted into our application at joinpoints.
A pointcut defines at what joinpoints advice should be applied. Advice can be applied at any joinpoint supported by the AOP framework. Of course, you don’t want to apply all of your aspects at all of the possible joinpoints. Pointcuts allow you to specify where you want your advice to be applied. Often you specify these pointcuts using explicit class and method names or through regular expressions that define matching class and method name patterns. Some AOP frameworks allow you to create dynamic pointcuts that determine whether to apply advice based on runtime decisions, such as the value of method parameters.
Applying an Aspect
The above Figure illustrates the key AOP concepts in action. The advice contains the crosscutting behavior that needs to be applied. The joinpoints are all the points within the execution flow of the application that are candidates to have advice applied. The pointcut defines at what joinpoints that advice is applied. The key concept you should take from this? Pointcuts define which joinpoints get advised.
Now lets continue with the other jargons in AOP.
An introduction allows you to add new methods or attributes to existing classes. For example, you could create an Auditable advice class that keeps the state of when an object was last modified. This could be as simple as having one method, setLastModified(Date), and an instance variable to hold this state. This can then be introduced to existing classes without having to change them, giving them new behavior and state.
A target is the class that is being advised. This can be either a class you write or a third-party class to which you want to add custom behavior. Without AOP, this class would have to contain its primary logic plus the logic for any cross-cutting concerns. With AOP, the target class is free to focus on its primary concern, oblivious to any advice being applied.
A proxy is the object created after applying advice to the target object. As far as the client objects are concerned, the target object (pre-AOP) and the proxy object (post-AOP) are the same—as it should be. That is, the rest of your application will not have to change to support the proxy class.
Weaving is the process of applying aspects to a target object to create a new, proxied object. The aspects are woven into the target object at the specified joinpoints. The weaving can take place at several points in the target class’s lifetime:
- Compile time—Aspects are woven in when the target class is compiled. This requires a special compiler.
- Classload time—Aspects are woven in when the target class is loaded into the JVM. This requires a special ClassLoader that enhances that target class’s bytecode before the class is introduced into the application.
- Runtime—Aspects are woven in sometime during the execution of the application. Typically, an AOP container will dynamically generate a proxy class that will delegate to the target class while weaving in the aspects.
AOP is a concept, so it is not bound to a specific programming language. In fact, it can help with the shortcomings of all languages (not only OO languages) that use single, hierarchical decomposition. AOP has been implemented in different languages (for example, C++, Smalltalk, C#, C, and Java).
Of course, the language that gains a great interest of the research community is the Java language. The following are the major tools that support AOP with Java: