ESB(Enterprise Service Bus)的框架实现企业应用
微软公司最近提供一套用于帮助企业实现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接口:
/// <summary>
/// IExceptionHandler 在关闭异常之前,用户可以通过自定义的IExceptionHandler来处理异常,比如记录为日志或显示错误信息给用户
/// </summary>
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))
{
return ;
}
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
{
get
{
return typeof(ExceptionHandler) ;
}
}
public EnterpriseServerBase.Aop.MultiAspect.AspectSwitcherState DefaultAspectSwitcherState
{
get
{
return AspectSwitcherState.On;
}
}
#endregion
}
我们还需要实现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 !") ;
}
}
#endregion
}
前面的代码很容易明白,异常处理只是将异常信息显示给用户。现在来看看如何使用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() ;
}
———————————————————————
任何美好的事物只有触动了人们的心灵才变的美好;
孤独的时候看看天空里的雨,其实流泪的不只是你。
人生只有走出来的美丽,没有等出来的辉煌!
———————————————————————