求知 文章 文库 Lib 视频 iPerson 课程 认证 咨询 工具 讲座 Modeler   Code  
会员   
 
  
 
 
     
   
分享到
CQRS架构案例Tiny Library CQRS详解:AOP拦截与异常处理
 

发布于2012-7-19

 

实现AOP拦截

如上所述,Tiny Library CQRS利用了Apworks框架实现AOP拦截,那么首先来了解一下Apworks支持AOP拦截的方式。Apworks采用Castle DynamicProxy实现AOP拦截,因此针对AOP拦截部分的开发,我们需要借助Castle DynamicProxy框架。在此说明一下,虽然Apworks极力使用分离接口模式(Separated Interface Pattern,PoEAA)来降低核心模块对第三方组件的耦合度(这部分内容我会在《.NET应用框架架构设计实践》系列文章中介绍),但与仓储、消息总线的实现相比,AOP更为核心,因此Apworks框架的核心模块直接依赖于Castle DynamicProxy。要基于Apworks实现AOP拦截,可以参考并遵循以下几个步骤:

定义拦截器(Interceptor)

首先在你的项目中定义一个拦截器(Interceptor),使其实现Castle.DynamicProxy.IInterceptor接口,该接口位于Castle.Core.dll程序集中,是与Apworks一起发布的。该接口只需要实现Intercept方法即可,在此方法中执行你自己的逻辑,然后使用invocation.Proceed方法将调用传递下去。需要注意的是,当invocation.Proceed发生异常的时候,如果被拦截的方法有返回值,那么你需要捕获异常并同时设置invocation.ReturnValue属性,否则会从Castle.DynamicProxy中抛出新的异常,而覆盖掉原始的异常信息。代码大致如下:

				
public class MyInterceptor : IInterceptor
{
    #region IInterceptor Members
    public void Intercept(IInvocation invocation)
    {
        try
        {
            invocation.Proceed();
        }
        catch (Exception ex)
        {
            invocation.ReturnValue = xxx; // Required!!
        }
    }
    #endregion
}  

Apworks框架在其Apworks.Interception命名空间下提供了一个用于异常处理的内建拦截器,在后面我会介绍这个拦截器。

配置Apworks框架

为了使用自定义的拦截器,我们需要配置Apworks框架,具体表现就是在web.config或者app.config配置文件中的apworks节点下,设置与AOP拦截相关的信息。这些信息包括:需要为哪些类型的哪些方法调用启用AOP拦截?采用什么拦截器去处理这些被拦截的方法?每个方法又支持哪些拦截器?比如,在Tiny Library CQRS中,AOP拦截的配置信息如下:

				
<apworks>
  <!-- ignored -->
  <interception>
    <interceptors>
      <interceptor name="exception" 
        type="Apworks.Interception.ExceptionHandlingInterceptor, 
              Apworks, Version=2.0.4259.25929, Culture=neutral, PublicKeyToken=8dd847f02992a80e" />
    </interceptors>
    <contracts>
      <contract 
        type="TinyLibraryCQRS.Infrastructure.TinyLibraryCQRSDomainRepository, 
              TinyLibraryCQRS.Infrastructure, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null">
        <methods>
          <method signature="System.Void Commit()">
            <interceptorRefs>
              <interceptorRef name="exception" />
            </interceptorRefs>
          </method>
        </methods>
      </contract>
      <contract 
      	 type="TinyLibraryCQRS.Model.Services.IUserAccountBookTransferService, 
      	       TinyLibraryCQRS.Model, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null">
        <methods>
          <method signature="System.Void BorrowBookToUser(TinyLibraryCQRS.Model.UserAccount, 
TinyLibraryCQRS.Model.Book)">
            <interceptorRefs>
              <interceptorRef name="exception" />
            </interceptorRefs>
          </method>
          <method signature="System.Void ReturnBookFromUser(TinyLibraryCQRS.Model.UserAccount, 
TinyLibraryCQRS.Model.Book)">
            <interceptorRefs>
              <interceptorRef name="exception" />
            </interceptorRefs>
          </method>
        </methods>
      </contract>
    </contracts>
  </interception>
</apworks> 

在上面的配置节点中,interceptors下注册了一个拦截器,即Apworks.Interception.ExceptionHandlingInterceptor(如果你按上面的步骤自己开发了一个拦截器,那么你也可以在这里进行配置,以使用自定义的拦截器),之后的contracts节点下定义了需要被拦截的类型与方法。在方法定义下,又使用interceptorRef来定义应该由哪个(或哪些)拦截器来处理这个方法。从整个inteception的配置节点来看,Apworks对AOP拦截的支持还是比较灵活的。

查看Apworks.Interception.ExceptionHandlingInterceptor的源代码,我们发现,在这个拦截器中,一旦invocation.Proceed方法出现异常,就会使用Apworks.Exceptions.ExceptionManager来处理抛出的异常。ExceptionManager是通过异常处理器(Exception Handler)来处理异常的。在实际项目中,我们需要自定义异常处理器,并对Apworks框架进行配置以实现异常处理。

异常处理

Apworks支持灵活的异常处理方式。比如:可以针对特定的Exception类型设置异常处理器,也可以设置某个Exception类型,使得所有继承于该类型的所有异常共用一个异常处理器。现在介绍一下Tiny Library CQRS项目中的异常处理方式。

定义异常处理器(Exception Handler)

在项目中新建一个继承于Apworks.Exceptions.ExceptionHandler的类型,并实现DoHandle方法,在这个方法中直接对传入的Exception进行处理即可。比如,在Tiny Library CQRS案例中,TinyLibraryCQRS.Infrastructure项目下就包含了整个Tiny Library CQRS所用的GeneralExceptionHandler:

				
public class GeneralExceptionHandler : ExceptionHandler<Exception>
{
    /// <summary>
    /// Returns a <see cref="System.Boolean"/> value which indicates
    /// whether the exception was handled.
    /// </summary>
    /// <param name="ex">The exception to be handled.</param>
    /// <returns>True if the exception was handled, otherwise, false, and the
    /// exception will be re-thrown to its caller method.</returns>
    protected override bool DoHandle(Exception ex)
    {
        EventLog.WriteEntry(Utils.EventLogApplication, ex.ToString(), EventLogEntryType.Error);
        return false;
    }
}
  

很明显,在Tiny Library CQRS中,当被拦截的方法发生异常时,GeneralExceptionHandler会直接将捕获的异常写入系统的事件日志(Event Log),同时返回false布尔值以表示该异常需要继续抛出。

配置Apworks框架

以下是Tiny Library CQRS案例中Command Service的web.config配置文件下,与异常处理相关的Apworks配置节点:

				
<apworks>
  <!-- ignored -->
  <exceptions>
    <exception type="System.Exception, mscorlib, Version=4.0.0.0, Culture=neutral, 
                     PublicKeyToken=b77a5c561934e089" behavior="Direct">
      <handlers>
        <handler type="TinyLibraryCQRS.Infrastructure.GeneralExceptionHandler, TinyLibraryCQRS.Infrastructure,
                        Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />
      </handlers>
    </exception>
  </exceptions>
  <!-- ignored -->
</apworks>  

该配置信息表明,当捕获到System.Exception(及继承于它的Exception)时,就使用TinyLibraryCQRS.Infrastructure.GeneralExceptionHandler进行异常处理。

检验Tiny Library CQRS的异常处理

现在让我们通过模拟会产生异常的应用场景,来检验Tiny Library CQRS的异常处理。

  • 停止Message Queuing服务的运行,使得TinyLibraryCQRSDomainRepository在做事务提交的时候发生异常

  • 在Tiny Library CQRS上以daxnet/daxnet账户登录,单击Books菜单,然后在图书列表中,单击《A Programmer’s Guide to .NET》一书最右边的Borrow按钮,在弹出的确认框中单击OK以确认借阅该图书

  • 此时页面提示错误信息“Message Queue service is not available.”

  • 查看系统的事件日志,发现产生了一条TinyLibraryCQRS的错误记录如下:


相关文章

企业架构、TOGAF与ArchiMate概览
架构师之路-如何做好业务建模?
大型网站电商网站架构案例和技术架构的示例
完整的Archimate视点指南(包括示例)
相关文档

数据中台技术架构方法论与实践
适用ArchiMate、EA 和 iSpace进行企业架构建模
Zachman企业架构框架简介
企业架构让SOA落地
相关课程

云平台与微服务架构设计
中台战略、中台建设与数字商业
亿级用户高并发、高可用系统架构
高可用分布式架构设计与实践

 
分享到
 
 
     


专家视角看IT与架构
软件架构设计
面向服务体系架构和业务组件
人人网移动开发架构
架构腐化之谜
谈平台即服务PaaS


面向应用的架构设计实践
单元测试+重构+设计模式
软件架构师—高级实践
软件架构设计方法、案例与实践
嵌入式软件架构设计—高级实践
SOA体系结构实践


锐安科技 软件架构设计方法
成都 嵌入式软件架构设计
上海汽车 嵌入式软件架构设计
北京 软件架构设计
上海 软件架构设计案例与实践
北京 架构设计方法案例与实践
深圳 架构设计方法案例与实践
嵌入式软件架构设计—高级实践
更多...