Table of Contents
Aspect-oriented programming (AOP) compliments object-oriented programming by empowering the modularization of crosscutting concerns, repeated code scattered throughout an application. Unlike their "cut and paste" brethren, identifying crosscutting concerns typically isn't as simple as looking for the same code repeated verbatim in several places. Unnecessarily mixed responsibilities can be symptomatic of crosscutting concerns; for example caching logic may be embedded in your business logic mixing dependencies and responsibilities and is therefore a crosscutting concern. AOP enables you to abstract and decouple these concerns. Other examples of crosscutting concerns include:
The following code example highlights the logging crosscutting concern. As you can see, the logging code varies slightly from location to location with the containing class and method making for error prone maintenance. If our logging API or process changes, we will have to touch every class in our system. AOP enables us to isolate this crosscutting dependency on the logging API to one spot, just as a class does for a domain object.
Example 1.1. Logging is a crosscutting concern.
class Foo { Log log = Log.getLog(Foo.class); void foo(String s) { log.log("*** invoked foo(" + s + ")"); // business logic... log.log("*** returned: void"); } void foo(int a, int b) { log.log("*** invoked foo(" + a + ", " + b + ")"); // business logic... log.log("*** returned: void"); } } class Bar { Log log = Log.getLog(Bar.class); String bar(String s) { log.log("*** invoked bar(" + s + ")"); // business logic... String result = ...; log.log("*** returned: " + result); return result; } }
An aspect is the AOP equivalent of a class. Just as a class contains methods and fields, an aspect contains advice and rules for applying advice.
Advice is the code portion of an aspect, more specifically the logic that replaces your crosscutting concern.
An interceptor is the first of the two types of advice we'll talk about. An interceptor simply intercepts events. Most commonly, an interceptor intercepts method invocations. In our logging example, we log messages at the beginning and end of method invocations. We can use an interceptor to execute logic such as this before and after a method invocation.
Introduction is the second type of advice and involves adding functionality to a class. In our logging example, we had a Log instance for each class type. In some AOP frameworks, we might introduce this Log field to our class.
The term mixin is commonly used in reference to introducing a mixin class. The mixin methods are added to the target class and their implementation delegates to a mixin instance.