微軟公司最近提供一套用于幫助企業實作ESB(Enterprise Service Bus)的架構,這套ESB架構是基于BizTalk Server的,ESB不是微軟公司的專利,許多大公司例如IBM 都有自己的ESB産品,當一個企業發展到了一定規模的時候,會有很多套成熟的軟體共同來支撐企業的營運,是以當一個企業的資訊化建設過程,必定會需要對多個業務系統進行整合,統一管理,統一協調。同時微軟公司已經成功的釋出了WCF ,這樣企業內建中的安全性得以解決,這也意味着在進行企業EAI的時候可以通過把各個子系統釋出成WCF 的EndPoint,通過ESB架構整合起來。
Microsoft ESB Guidance 利用BizTalk Server 強大功能去支援松耦合的消息架構,Microsoft ESB Guidance正是利用了BizTalk Server這些特性去實作企業的ESB ,BizTalk Server 支援強大釋出訂閱功能,也就是說Microsoft ESB Guidance是以BizTalk Server 為消息總線,所有的消息經過經過訂閱者發送到BizTalk Server 的消息資料庫中,然後處理轉發給其他的訂閱者,每個訂閱者可以通過WCF 技術暴露出很多個不同端口的EndPoint。這樣所有的服務都是獨立的無序性的,并且是解耦的
微軟通過一些列的産品Windows Server 2003, the .NET Framework 3.0, and BizTalk Server 2006作為對企業實作ESB的支撐,Microsoft ESB Guidance是基于BizTalk Server 2006一組應用,它提供以下公用的ESB元件:
· Message routing (消息路由)
· Message validation (消息驗證)
· Message transformation (消息轉換)
· Centralized exception management(集中的異常管理)
· Extensible adapter framework(可擴充的擴充卡架構)
· Service orchestration(服務的編制支援)
· Business rules engine(業務規則引擎)
· Business activity monitoring(業務活動監視)
以我自己的異常處理經驗,我通常會在UI事件處理函數或線程啟動函數中截獲所有的異常,然後對截獲的異常作特定的處理--很多情況下,是顯示一個錯誤資訊給使用者,或記錄異常日志!在這“很多情況下”,我都需要做相同的工作,首先是用try...catch把UI事件處理函數或線程啟動函數中的所有代碼圍起來,然後,可能就是MessageBox.Show(ex.Message)或其它的處理。
大家已經想到了,這類事情正好可以使用AOP來完成。本文将在前文介紹的EsbAOP的基礎上來開發一個異常關閉器方面--ExceptionCloseerAspect,該方面修飾UI操作或修飾background線程的啟動函數,用于控制是否攔截被修飾的方法抛出的異常,如果攔截,則對異常進行使用者自定義處理,然後關閉該異常。
關于ExceptionCloseerAspect要注意以下幾個方面:
(1)在UI操作時或背景線程中,經常其中會通路資料庫或網絡,為了截獲這些異常,需要在每個UI的事件處理函數中寫try...catch, 如果使用ExceptionCloseerAspect,則就不用在寫try-catch了,ExceptionCloseerAspect會自動幫我們把異常截獲,然後關閉它。
(2)ExceptionCloseerAspect通常用于系統結構的最上層,比如UI層、或background線程的啟動函數處。而且正好這些函數的傳回值為void。
(3)使用者可以通過實作IExceptionHandler自定義異常處理方案,比如記錄異常日志、彈出消息框通知使用者等。
(4)注意,一般UI從Form繼承,是以無法再從ContextBoundObject繼承,也就無法對其使用Aspect,是以需要把最上層的邏輯封裝在一個單獨的類中==》而這有助于UI與邏輯的分離!
從前面的分析已經看到,線程有兩種類型,一是主線程(通常為UI線程),一是背景線程,對于不同線程抛出的異常,使用者可能需要作不同的處理,是以,我們使用枚舉來定義線程類型:
/// <summary>
/// ExceptionCloseType 異常發生所線上程的類型
/// </summary>
public enum ExceptionHostType
{
NotSetted ,UIThread ,BackGroundThread
}
而為了使使用者有機會處理抛出的異常,我們提供了IExceptionHandler接口:
/// IExceptionHandler 在關閉異常之前,使用者可以通過自定義的IExceptionHandler來處理異常,比如記錄為日志或顯示錯誤資訊給使用者
public interface IExceptionHandler
void HandleException(Exception ee ,ExceptionHostType hostType) ;
}
在這些基礎之上,我們就可以來實作ExceptionCloseerAspect了。從前文可以知道,ExceptionCloseerAspect隻需要實作IAspect接口就可以了。現在給出其實作:
public class ExceptionCloseerAspect :IAspect
public ExceptionCloseerAspect()
{
}
#region IAspect 成員
public void PreProcess(IMethodCallMessage requestMsg, object aspectClassArgument, object aspectMethodArgument)
{
public void PostProcess(IMethodCallMessage requestMsg, ref IMethodReturnMessage respond, object aspectClassArgument, object aspectMethodArgument)
if(respond.Exception == null)
{
return ;
}
Type HandlerType = (Type)aspectClassArgument ;
Type destType = typeof(IExceptionHandler) ;
if(! destType.IsAssignableFrom(HandlerType))
IExceptionHandler exceptionHandler = (IExceptionHandler)Activator.CreateInstance(HandlerType) ;
if(aspectMethodArgument != null)
exceptionHandler.HandleException(respond.Exception ,(ExceptionHostType)aspectMethodArgument) ;
else
exceptionHandler.HandleException(respond.Exception ,ExceptionHostType.NotSetted) ;
//修改傳回結果,關閉異常
respond = new ReturnMessage(null ,requestMsg) ;
#endregion
上面的實作有幾點需要說明:
(1)ExceptionCloseerAspect的aspectClassArgument是實作了IExceptionHandler接口的類型
(2)ExceptionCloseerAspect的aspectMethodArgument是ExceptionHostType枚舉值之一。
(3)注意PostProcess方法實作的最後一句,是AOP修改了方法調用的結果,進而關閉了異常。
在實作了異常關閉器之後,我們就可以來小試牛刀了。首先,我們需要實作IAspectProcessorWrap接口來把ExceptionCloseerAspect所需要的資源反應出來:
public class ExceptionClosserWrap :IAspectProcessorWrap
#region IAspectProcessorWrap 成員
public Type AspectProcessorType
get
{
return typeof(ExceptionCloseerAspect);
public object AspectClassArgument
return typeof(ExceptionHandler) ;
public EnterpriseServerBase.Aop.MultiAspect.AspectSwitcherState DefaultAspectSwitcherState
return AspectSwitcherState.On;
我們還需要實作IExceptionHandler來處理異常:
public class ExceptionHandler :IExceptionHandler
#region IExceptionHandler 成員
public void HandleException(Exception ee, ExceptionHostType hostType)
if(hostType == ExceptionHostType.UIThread)
MessageBox.Show(ee.Message + "UI Thread !") ;
if(hostType == ExceptionHostType.NotSetted)
MessageBox.Show(ee.Message + " host thread not setted !") ;
if(hostType == ExceptionHostType.BackGroundThread)
MessageBox.Show(ee.Message + " background thread !") ;
前面的代碼很容易明白,異常處理隻是将異常資訊顯示給使用者。現在來看看如何使用ExceptionCloseerAspect。需要再次強調的是,ExceptionCloseerAspect通常作用于UI事件處理函數或線程啟動函數。我們已一個UI事件處理函數作為例子,首先要保證UI與業務邏輯分離,是以,我将業務邏輯封裝在MyBusiness類中:
[Aspect(typeof(ExceptionClosserWrap))]
public class MyBusiness :ContextBoundObject
[AspectSwitcher(typeof(ExceptionClosserWrap) ,true ,ExceptionHostType.UIThread)]
public void OnButton1Click()
throw new Exception("sky test exception !") ;
[AspectSwitcher(typeof(ExceptionClosserWrap) ,true)]
public void OnButton2Click()
throw new Exception("sky2 test exception !") ;
[AspectSwitcher(typeof(ExceptionClosserWrap) ,true ,ExceptionHostType.BackGroundThread)]
public void SkyThread()
throw new Exception("backGround thread exception !") ;
而在所有的UI事件處理函數中,都将調用MyBusiness對應的方法,如:
private void button1_Click(object sender, System.EventArgs e)
this.myBusiness.OnButton1Click() ;
private void button2_Click(object sender, System.EventArgs e)
this.myBusiness.OnButton2Click() ;
private void button3_Click(object sender, System.EventArgs e)
Thread thread = new Thread(new ThreadStart(this.myBusiness.SkyThread)) ;
thread.Start() ;
本文轉自
高陽 51CTO部落格,原文連結http://blog.51cto.com/xiaoyinnet/196447: ,如需轉載請自行聯系原作者