Up until now we have only seen constructs that allow us to implement dynamic crosscutting, crosscutting that changes the way a program executes. AspectJ also allows us to implement static crosscutting, crosscutting that affects the static structure of our progams. This is done using forms called introduction.
An introduction is a member of an aspect, but it defines or modifies a member of another type (class). With introduction we can
Suppose we want to change the class Point to support cloning. By using introduction, we can add that capability. The class itself doesn't change, but its users (here the method main) may. In the example below, the aspect CloneablePoint does three things:
declares that the class Point implements the interface Cloneable,
declares that the methods in Point whose signature matches Object clone() should have their checked exceptions converted into unchecked exceptions, and
adds a method that overrides the method clone in Point, which was inherited from Object.
class Point { private int x, y; Point(int x, int y) { this.x = x; this.y = y; } int getX() { return this.x; } int getY() { return this.y; } void setX(int x) { this.x = x; } void setY(int y) { this.y = y; } public static void main(String[] args) { Point p = new Point(3,4); Point q = (Point) p.clone(); } } aspect CloneablePoint { declare parents: Point implements Cloneable; declare soft: CloneNotSupportedException: execution(Object clone()); Object Point.clone() { return super.clone(); } }
Introduction is a powerful mechanism for capturing crosscutting concerns because it not only changes the behavior of components in an application, but also changes their relationship.