手頭上的一個項目使用了Spring.net的AOP了處理程式的異常,一不小心就掉進了陷阱,這裡記錄下來,希望對後來者有所幫助。Spring.net的AOP實作是通過運作時建立動态的AOP代理來完成的。簡單圖示如下:
![](https://img.laitimes.com/img/_0nNw4CM6IyYiwiM6ICdiwiInBnauUjNihzNmJGN4MDNkNTYhNzMkBDOiVmZilTZlJzY2EjYfdWbp9CXt92Yu4GZjlGbh5SZslmZxl3Lc9CX6MHc0RHaiojIsJye.jpg)
圖中的“POJO”以詞來自Java,表示一個普通的.net對象,所有對POJO的調用都要經過Aop代理進行,是以Aop才有機會插入Pre_Action、Post_Action、和Around_Action。
現在我以手上的工作舉個例子,看我是如何掉入陷阱的:
public interface IIrasRemotingServiceAccesser
{
void Initialize() ;
void fsManager_AsServiceListChanged(int serverID, string serverName, ArrayList serviceList) ;
void CheckMySelf() ;
}
我們沒有必要了解IIrasRemotingServiceAccesser接口的具體用途,隻要了解這個接口将被Aop代理,為了使Aop能夠截獲fsManager_AsServiceListChanged方法,我把它放入了接口定義中,實際上它是一個事件處理函數,本應是私有的。
Initialize方法使用fsManager_AsServiceListChanged預定了某個事件:
public void Initialize()
{
this.fsManager.AsServiceListChanged += new CbServiceChanged(fsManager_AsServiceListChanged);
}
運作程式後,發現CheckMySelf方法能正常被AOP截獲,而當fsManager.AsServiceListChanged事件發生時,對fsManager_AsServiceListChanged的調用沒有被截獲。
這是為什麼?
原來是預定事件時,繞過了AOP代理:
this.fsManager.AsServiceListChanged += new CbServiceChanged(this.fsManager_AsServiceListChanged);
請注意紅色的“this”,正是它繞過了AOP代理。是以fsManager_AsServiceListChanged的調用沒有被截獲。解決方案?我常用的有兩種:
(1)将this換為代理:
{
IIrasRemotingServiceAccesser myAopProxy = (IIrasRemotingServiceAccesser)MainClass.SpringContext.GetObject("irasRemotingServiceAccesser") ;
this.fsManager.AsServiceListChanged += new CbServiceChanged(myAopProxy.fsManager_AsServiceListChanged);
可以看到,myAopProxy.fsManager_AsServiceListChanged被委托為事件處理函數,這是通過Aop代理myAopProxy進行。這種方法解決了問題,但是又引入了新的問題--IIrasRemotingServiceAccesser實作類不再是一個“POJO”,而是依賴于Spring.net架構了。更好的辦法是第二種:
void ChangeServiceList(int serverID, string serverName, ArrayList serviceList) ;
}
如此,原來Initialize方法中的事件預定就轉移到Bridge中了,是以就避免了繞過AOP代理的情況。