AspectC++ join point,pointcut,advice,aspect,slices, introduction

AOP的核心思想是对横切关注点进行模块化。Aspect C++是针对C++的AOP扩展。

  • join point:运行aspects的代码部分,可以使类、结构、联合、对象、控制流

    execution join point与可执行函数名关联。纯虚函数不可执行,因此可执行join point的advice代码不能应用于纯虚函数。但纯虚函数的调用,即这类函数作为call join point,是可以的。
    call join point与两个名字相关:源(调用者)名字和调用的目标函数(被调用者)的名字。由于同一个函数中会有很多函数调用,每个函数名可以被关联到一系列的call join point。
    construction join point为当创建实例时。destruction join point对应于析构实例。

  • pointcut:是join point的集合。用来定义在什么地方插入advice代码,进行横向切入。类似于C++中的变量,只不过带个括号。定义格式: pointcut 变量名() = 标志符( ||标志符…… )

    匹配表达式(name pointcut)
    "int C::%(...)"
           匹配所有类C中返回值为int的成员函数;
    "%List"
           匹配任意以“List”为结尾的类、结构、联合或枚举;
    "% printf(const char *, ...)"
           匹配全局域中名字为print、拥有至少一个const char *型形参、返回任意类型的函数;
    "const %& ...::%(...)"
           匹配所有返回值为const reference的函数;
    
    pointcut表达式
    "%List" && !derived("Queue")
           描述以List结尾、不派生自基类Queue的所有类;
    call("void draw()") && within("Shape")
           描述所有对类Shape中void draw()方法的调用;
    
    pointcut声明
    pointcut lists() = derived("List");
    
  • advice:定义横向切入时加到pointcut的代码。有一点像C中的函数,只不过这个函数自己指定了他运行的地方(pointcut)。当然加的代码不局限于函数,也可以是data。advice只能定义与aspect声明中。定义函数的格式: advice pointcut名() : 函数返回值 advice类型名() { 代码 }

    advice execution("void login(...)") : before() {
    cout < < "Logging in." < < endl;
    }
    

    pointcut表达式后的代码段“:before()”表明,advice代码再code join point到达前执行。
    “:after()”同理。
    “:around()”表示执行advice代码,不执行code join point代码。
    这种情况下,如果需要执行code join point代码,需要显示的通过proceed()指明。
    程序中的代码没有访问advice代码的权限。

    可以访问上下文信息的advice声明
    pointcut new_user(const char *name) = execution("void login(...)") && args(name);
    advice new_user(name) : before(const char *name) {
    cout < < "User " < < name < < " is logging in." < < endl;
    }
    
  • aspect:类似于C++中的class,但aspect不仅包含data、function,还包含advice。aspect可以从class派生而来,反之不行。aspect的定义和class一样,区别仅仅在于里面包含advice的声明或定义。

  • slices:slice是C++语言元素中定义一个范围的段落。advice可利用slice扩展程序的静态结构。例如,利用advice,class类型slice中的元素可被加到一个或多个目标类中。

    slice class Chain {
    Chain *_next;
    public:
    Chain *next () const { return _next; }
    };
    
    
  • introduction:AspectC++支持的第二种advice是introduction。introduction用于扩展程序代码和数据。

    和普通advice声明相同,introduction也以关键字advice打头。如果advice后的pointcut是name pointcut,那么“:”之后的slice声明就被引入(introduce)到pointcut所规定类或aspects中。
    使用引入的代码和使用普通程序代码一样。
    introduction中的advice代码拥有join point处程序代码的完全访问权限,引入到class中的方法能够访问该class的私有成员。

    pointcut shapes() = "Circle" || "Polygon";
    advice shapes() : slice class {
    	bool m_shaded;         
    	void shaded(bool state) {
    	m_shaded = state;
    	}
    };
    
    
    引入基类
    advice "%Object" : slice class : public MemoryPool {
    virtual void release() = 0;
    }
    
发布了55 篇原创文章 · 获赞 3 · 访问量 6614
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章