AOP的核心思想是对横切关注点进行模块化。Aspect C++是针对C++的AOP扩展。
join point:运行aspects的代码部分,可以使类、结构、联合、对象、控制流。
pointcut:是join point的集合。用来定义在什么地方插入advice代码,进行横向切入。类似于C++中的变量,只不过带个括号。定义格式如下:
pointcut 变量名() = 标志符( ||标志符…… );
ex:pointcut move() = calls( “void FigureElement::setXY(int int)” ) || calls( “void Point::set%(int)” );
说明:1. 引号中间的是要横向切入的地方;通配符“%”表示任何;||表示或,是算数逻辑;
2.标志符是定义好的,包括calls等待。具体看参考文献1。
advice:定义横向切入时加到pointcut的代码。有一点像C中的函数,只不过这个函数自己指定了他运行的地方(pointcut)。当然加的代码不局限于函数,也可以是data。advice只能定义与aspect声明中。定义函数的格式如下:
advice pointcut名() : 函数返回值 advice类型名() { 代码 }
ex:advice move():void after () { cout << “a figure element woa moved.” << endl; }
说明: 1. 这个例子就是在void FigureElement::setXY(int int)函数和void Point::set%(int)函数运行之后输出“a figure element woa moved.”。
2.advice类型名就相当于C中的函数名,有几个是定义好的:before、after、around。around和process()搭配使用。
3.advice类型名也可以是自己定义的。那就表示在所有pointcut中指定的地方插入该advice代码。
ex: pointcut all_classes() = classes(“%”); //所有的类都是pointcut;
advice all_classes(): void print(){ cout << “Address: ” << (void *)this << endl; }
说明:这个advice在所有的类中增加了成员函数print()。
4. pointcut名可以不是之前定义的,可以直接用标志符指定。但是被横向切入的函数的参数有点变化:字符串中不写形参类型,只写形参名;在advice类型名后的括号中写上完整的形参声明。
ex:advice calls(“void FigureElement::setXY(x, y)”):void after( int x, int y ){ //code }
定义data的例子:advice classes(“otherNamespace::%”):Registry r;
aspect: 类似于C++中的class,但aspect不仅包含data、function,还包含advice。aspect可以从class派生而来,反之不行。aspect的定义和class一样,区别仅仅在于里面包含advice的声明或定义。
ex:aspect classCounter of all_classes()
{
int count; //data member
public:
classCounter(){ count = 0; } //ctor
advice all_classes(): void dump() ; //advice的声明。
};
void classCounter::dump() //advice的定义,和class成员函数的类外定义格式一样。
{ count++: }
说明:这里有个“of”,后面加一个pointcut变量。表示每个pointcut都有一个独立的classCounter,否则,所有pointcut共有一个全局的classCounter。有了of之后,每个类都有独立的count。这里of之后的pointcut必须包含某种统一类型的join point。
参考文献:Aspect C++:Language Proposal and Prototype Implementation.