AspectJ学习之Introduction

Posted on 一 30 三月 2015 in Reading

The AspectJ Programming Guide第一章的笔记

1. 四个constructs:pointcuts, advice, inter-type declarations and aspects

  • Pointcuts and advice dynamically affect program flow
  • inter-type declarations statically affects a program’s class hierarchy
  • and aspects encapsulate these new constructs.

A join point is a well-defined point in the program flow. A pointcut picks out certain join points and values at those points. A piece of advice is code that is executed when a join point is reached. These are the dynamic parts of AspectJ.(动态织入)

AspectJ also has different kinds of inter-type declarations that allow the programmer to modify a program’s static structure, namely, the members of its classes and the relationship between classes.(静态织入)

AspectJ’s aspect are the unit of modularity for crosscutting concerns. They behave somewhat like Java classes, but may also include pointcuts, advice and inter-type declarations.(类似于class)

2.定义pointcut点

全名:关键字call

call(void Point.setX(int))

逻辑语句:

call(void Point.setX(int)) || call(void Point.setY(int))

别名/命名:move()代表这个pointcut

pointcut move():
    call(void FigureElement.setXY(int,int)) ||
    call(void Point.setX(int))

pointcut的pointcut:关键字cflow,控制流(control-point),监测获取整个控制流

cflow(move())

3.advince:

  • Before advince:在执行pointcut的方法之前执行(但在获得参数后)
  • After advince:在执行pointcut的方法之后执行(但在return之前)
  • Around advince:貌似是可以指定在方法运行到什么地方的时候执行该advince(on a join point runs as the join point is reached, and has explicit control over whether the program proceeds with the join point.)
  • 暴露pointcut的上下文:

    格式如下:

    after(FigureElement fe, int x, int y) returning:
        ...SomePointcut... {
        ...SomeBody...
    }
    

    表示这个AfterAdvince可以获得pointcut的环境中的三个参数。使用匿名pointcut:

    after(FigureElement fe, int x, int y) returning:
        call(void FigureElement.setXY(int, int)) && target(fe) && args(x, y) {
        System.out.println(fe + " moved to (" + x + ", " + y + ")");
    }
    

    使用命名的pointcut:

    pointcut setXY(FigureElement fe, int x, int y):
        call(void FigureElement.setXY(int, int)) && target(fe) && args(x, y);
    after(FigureElement fe, int x, int y) returning: setXY(fe, x, y) {
        System.out.println(fe + " moved to (" + x + ", " + y + ").");
    }
    

4. 类型间声明(Inter-type declarations)

是切入类和它们层次结构的声明。定义一个Point类的观察者:

aspect PointObserving {
    private Vector Point.observers = new Vector();
    ...
}

添加访问这个私有成员的方法

aspect PointObserving {
    private Vector Point.observers = new Vector();

    public static void addObserver(Point p, Screen s) {
        p.observers.add(s);
    }
    public static void removeObserver(Point p, Screen s) {
        p.observers.remove(s);
    }
    ...
}

添加切入点changes,以便观察变化

aspect PointObserving {
    private Vector Point.observers = new Vector();

    public static void addObserver(Point p, Screen s) {
        p.observers.add(s);
    }
    public static void removeObserver(Point p, Screen s) {
        p.observers.remove(s);
    }

    pointcut changes(Point p): target(p) && call(void Point.set*(int));

    after(Point p): changes(p) {
        Iterator iter = p.observers.iterator();
        while ( iter.hasNext() ) {
            updateObserver(p, (Screen)iter.next());
        }
    }

    static void updateObserver(Point p, Screen s) {
        s.display(p);
    }
}

5. 切面(Aspect)

Aspects wrap up pointcuts, advice, and inter-type declarations in a a modular unit of crosscutting implementation. 类似一个类。

不可以new出一个Aspect,默认情况它是单例的。这意味着,如果需要保持状态的话,advince可以使用一个非静态域:

aspect Logging {
    OutputStream logStream = System.err;

    before(): move() {
        logStream.println("about to move");
    }
}