A Tour of AOP
By now, it should be clear that AOP systems help in modularizing crosscutting concerns. However, so are many other solutions, such as direct byte code manipulation tools, for example, CGLIB or ASM, direct use of the proxy design pattern, or even meta-programming. How do you recognize AOP from all these other options? To find out, we need to distill core characteristics of AOP systems into a generic model. If a system fits that model, it is an AOP system; otherwise, it is not.
In order to implement a crosscutting concern, an AOP system may include many of the following concepts:
- Identifiable points in the execution of the system: Such points may include execution of methods, creation of objects, or throwing of an exception. Such identifiable points in the system are called join points. Note that join points are present in all systems even those that don’t use AOP, since join points are simply points during execution of a system. AOP merely gives identifies and categorizes these points.
- A construct for selecting join points: Implementing a crosscutting concern will require selecting a specific set of join points. For example, the tracing aspect discussed earlier needs to select only the public methods in the system. In AOP, the pointcut construct selects any join point that satisfies the criteria. This is similar to an SQL query selecting rows in database (we will compare AOP with databases in section 1.7.2). Pointcuts also collect context at the selected points. For example, a pointcut may collect method argument as context. The concept of join points and construct of pointcuts together form an AOP system’s join point model.
- A construct to alter program behavior: Once a pointcut selects join points, we need to augment those join points with additional or alternative behavior. For example, when implementing tracing, you need to log entry into the public methods. The advice construct in AOP provides a facility to do so. An advice adds behavior before, after, or around the selected join points. Around advice surrounds the join point execution and may execute it zero or more times. Advice is a form of dynamic crosscutting since it affects the execution of the system.
- A construct to alter static structure of the system: Sometimes, to implement dynamic crosscutting effectively, you need to alter the static structure of the system. For example, when implementing tracing, you may need to introduce the logger field into each traced class. The inter-type declaration constructs make such modifications possible. Furthermore, in some situations, you may need to detect certain conditions, typically the existence of particular join points, before an execution of the system. The weave-time declaration constructs allow such possibilities. Collectively, all these mechanisms are referred to as static crosscutting given their effect on the static structure, as opposed to dynamic behavior changes to the execution of the system.
- A module to express all crosscutting constructs: Since the end goal of AOP is to have a module that embeds crosscutting logic, you need a place to express that logic. The aspect construct provides such a place. An aspect will contain pointcuts, advice, and static crosscutting constructs. An aspect may be related to other aspects in similar way to a class relates to others. Furthermore, aspects are a part of the system and aspects use the system (for example classes in it) to get its work done.
Figure 2 shows all these players and their relationship to each other in an AOP system.
Each AOP system may choose a subset of the model. For example, Spring AOP does not implement weave-time declarations due to its emphasis on runtime nature. On the other hand, the join point model is so central to AOP that every AOP system must support it. Everything else revolves around the join point model.
When you encounter a solution that modularizes crosscutting concerns, try to map it onto the generic AOP model. If you can, then that solution is indeed an AOP system. Otherwise, it is an alternative approach for solving the problem of crosscutting concerns. In the next section, we look at some commonly known alternatives to AOP.
The problem AOP addresses isn’t new. The concerns of auditing, transaction management, security, and so on emerged as soon as we started implementing nontrivial software systems. Consequently, there are many competitive technologies to deal with the same problem: frameworks, code generation, design patterns, and dynamic languages. Let’s take a look at those alternatives. Note that, while I compare these techniques as alternative to AOP and (not surprisingly) show how AOP outshines each of them when it comes to dealing with crosscutting concerns, I do not mean that these techniques are useless. Each of these techniques is appropriate for a set of problems. In fact, AOP can work alongside these techniques quite well. Furthermore, in some cases, AOP can enhance their implementation.