2.5 运行时支持
2.5.1 建议代码支持
对于许多方向来说,访问上下文变量并不能获得关于建议代码激活的结合点的足够信息。例如,对于一个函数调用完整的日志控制流方向,我们需要关于函数参数和运行时类型的相关信息,这样才可能产生类型匹配的输出。
在AspectC++中,这一信息由类JoinPoint
的成员提供(见下表)。
JoinPoint
API的类和静态方法对每个建议代码激活是传递的信息都是相同的。而非静态方法在不同的激活里传递的信息是不同的。这些方法可以通过对象tjp
分别访问。JoinPoint
类型的thisJoinPoint
也一直可以在建议代码中访问到。
下面的例子演示了如何使用JoinPoint
API实现一个可复用的控制流方向。
例:可复用追踪方向
aspect Trace {
pointcut virtual methods() = 0;
advice execution(methods()) : around() {
cout << "before " << JoinPoint::signature() << "(";
for (unsigned i = 0; i < JoinPoint::args(); i++) {
printvalue(tjp->arg(i), JoinPoint::argtype(i));
}
cout << ")" << endl;
tjp->proceed();
cout << "after" << endl;
}
};
这个对象通过重新定义派生方向指定的虚点切将追踪代码编织到每个函数中。帮助者函数printvalue
负责格式化输出函数调用中给出的参数。在为每个参数调用printvalue
之后,实际结合点的程序代码通过调用JoinPoint
对象的proceed
执行。proceed
的功能通过使用这样的动作实现。
2.5.2 动作
在AspectC++中,动作是在运行的程序到达的结合点后建议代码不会激活后跟随的状态序列。因此tjp->proceed()
触发了结合点的程序代码的执行。这款也是函数的调用或者执行。动作概念可以在AC::Action
结构中查询到。事实上,proceed
等同于action().trigger()
,所以tjp->proceed()
也可以使用tjp->Action().trigger()
替代。因此JoinPoint
API的action()
方法实际上返回了结合点的真正的动作对象。
网友评论