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
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章