一、背景与动机
微软Enterprise Library ELAB(Exception Handling Application Block)提供了一种基于策略(Policy)的异常处理方式,在不同的环境中,比如多层架构中不同的层次中,我们可以定义不同的异常处理策略。对于ELAB来说,Exception Handling Policy = Exception Type + Exception Handler(s) ,也就是说异常处理策略规定了对于某种类型的类型需要通过那些Exception Handler去处理。
从这种意义上讲,ELAB的异常处理机制是基于Exception Type的,异常的类型是我们处理异常的最小粒度。对于一个确定的异常处理策略,在不同场合抛出的同种类型的异常,都会使用相同的Exception Handler去处理。举个例子,对于一个基于SQL Server的Data Access操作,对于数据库连接失败和违反数据一致性约束,都会抛出SqlException。这两种情况对于ELAB都是等效的,因为它只能根据异常的类型进行异常处理。
在很多情况下,这种基于异常类型级别的异常处理并不能解决我们实际异常处理的问题。我们往往需要粒度更细的异常处理机制——对于抛出的同一种类型的异常,根据异常对象具体的属性值进行相应的异常处理。
二、从基于类型的异常处理到基于属性值异常处理
我们需要实现的目标很清楚,就是对于抛出的异常,我们可以根据某个属性的具体的值,为其指定对应的Exception Handler进行处理。由于ELAB基于异常类型的Exception Handler的分发机制,我们不能改变,我们只能采用一些变通的机制实现“曲线救国”,达到我们基于属性的分发Exception Handler的目的。
具体的实现方案就是创建一个特殊的Exception Handler,该Exception Handler根据异常对象某个属性的值,指定相应的Exception Handler。对于这个特殊的Exception Handler来说,他实现了基于属性值的筛选功能,我们把它命名为FilterableExceptionHandler。
一般情况下,异常的类型和对应的Exception Handler通过下图的形式直接进行匹配。当FooException抛出,两个Exception Handler,ExceptionHandlerA和ExceptionHandlerB先后被执行。
当引入了FilterableExceptionHandler以后,整个结构变成下面一种形式:FilterableExceptionHandler被指定到FooException,当FooException被抛出的时候,FilterableExceptionHandler被执行。而FilterableExceptionHandler本身并不执行异常处理相关的逻辑,它的工作是根据exception的某个属性值,创建相对应的ExceptionHandler(s),并使用他们来处理该异常。如下图所示,当exception.Property=Value1是,创建ExceptionHandlerA和ExceptionHandlerB处理异常;当exception.Property=Value2时,真正创建出来进行异常处理的是ExceptionHandlerC和ExceptionHandlerD。
三、FilterableExceptionHandler的配置
接下来,我们就来创建这样一个特殊的FilterableExceptionHandler。和一般的自定义Exception Handler一样,除了定义FilterableExceptionHandler本身之外,还需要定义两个辅助的类:ExceptionHandlerData和ExceptionHandlerAssembler,前者定义ExceptionHandler相关的配置信息;后者通过配置创建相应的ExceptionHandler。
我们先来定于FilterableExceptionHandler的ExceptionHandlerData:FilterableExceptionHandlerData。在这之前,我们来看看一个FilterableExceptionHandler配置的实例:
1: <?xml version="1.0" encoding="utf-8"?>
<!--CRLF-->
2: <configuration>
<!--CRLF-->
3: <configSections>
<!--CRLF-->
4: <section name="exceptionHandling" type="Microsoft.Practices.EnterpriseLibrary.ExceptionHandling.Configuration.ExceptionHandlingSettings, Microsoft.Practices.EnterpriseLibrary.ExceptionHandling, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
<!--CRLF-->
5: </configSections>
<!--CRLF-->
6: <exceptionHandling>
<!--CRLF-->
7: <exceptionPolicies>
<!--CRLF-->
8: <add name="Exception Policy">
<!--CRLF-->
9: <exceptionTypes>
<!--CRLF-->
10: <add type="Artech.CustomExceptionHandlers.FooException,Artech.CustomExceptionHandlers.Demo"
<!--CRLF-->
11: postHandlingAction="ThrowNewException" name="Exception">
<!--CRLF-->
12: <exceptionHandlers>
<!--CRLF-->
13: <add type="Artech.ExceptionHandlers.FilterableExceptionHandler,Artech.ExceptionHandlers" name="Custom Handler">
<!--CRLF-->
14: <filters>
<!--CRLF-->
15: <add property="Message" value="xxx" name="filter1" typeConverter="System.ComponentModel.TypeConverter,System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<!--CRLF-->
16: <exceptionHandlers>
<!--CRLF-->
17: <add exceptionMessage="Bar" exceptionMessageResourceType=""
<!--CRLF-->
18: replaceExceptionType="Artech.CustomExceptionHandlers.BarException,Artech.CustomExceptionHandlers.Demo"
<!--CRLF-->
19: type="Microsoft.Practices.EnterpriseLibrary.ExceptionHandling.ReplaceHandler, Microsoft.Practices.EnterpriseLibrary.ExceptionHandling, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
<!--CRLF-->
20: name="Replace Handler" />
<!--CRLF-->
21: </exceptionHandlers>
<!--CRLF-->
22: </add>
<!--CRLF-->
23: <add property="Message" value="yyy" name="filter2" typeConverter="System.ComponentModel.TypeConverter,System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<!--CRLF-->
24: <exceptionHandlers>
<!--CRLF-->
25: <add exceptionMessage="Baz" exceptionMessageResourceType=""
<!--CRLF-->
26: replaceExceptionType="Artech.CustomExceptionHandlers.BazException,Artech.CustomExceptionHandlers.Demo"
<!--CRLF-->
27: type="Microsoft.Practices.EnterpriseLibrary.ExceptionHandling.ReplaceHandler, Microsoft.Practices.EnterpriseLibrary.ExceptionHandling, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
<!--CRLF-->
28: name="Replace Handler" />
<!--CRLF-->
29: </exceptionHandlers>
<!--CRLF-->
30: </add>
<!--CRLF-->
31: </filters>
<!--CRLF-->
32: </add>
<!--CRLF-->
33: </exceptionHandlers>
<!--CRLF-->
34: </add>
<!--CRLF-->
35: </exceptionTypes>
<!--CRLF-->
36: </add>
<!--CRLF-->
37: </exceptionPolicies>
<!--CRLF-->
38: </exceptionHandling>
<!--CRLF-->
39: </configuration>
<!--CRLF-->
40:
<!--CRLF-->
其中和FilterableExceptionHandler相关的配置集中在如下一段。整个配置的结果是这样的:<filters>中一个filter列表,定义了对异常对象属性名/属性值的筛选和符合该条件的Exception Handler列表。下面一段配置表达的场景是:对于抛出的异常(Artech.CustomExceptionHandlers.FooException,Artech.CustomExceptionHandlers.Demo),我们需要调用ReplaceHandler用一个另一个异常对其进行替换。具体的替换规则是:如何Message属性为“xxx”,则将其替换成BarException;如何Message属性为“yyy”,则替换成BazException。最终的Message分别为“Bar”和“Baz”。
1: <filters>
<!--CRLF-->
2: <add property="Message" value="xxx" name="filter1" typeConverter="System.ComponentModel.TypeConverter,System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<!--CRLF-->
3: <exceptionHandlers>
<!--CRLF-->
4: <add exceptionMessage="Bar" exceptionMessageResourceType=""
<!--CRLF-->
5: replaceExceptionType="Artech.CustomExceptionHandlers.BarException,Artech.CustomExceptionHandlers.Demo"
<!--CRLF-->
6: type="Microsoft.Practices.EnterpriseLibrary.ExceptionHandling.ReplaceHandler, Microsoft.Practices.EnterpriseLibrary.ExceptionHandling, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
<!--CRLF-->
7: name="Replace Handler" />
<!--CRLF-->
8: </exceptionHandlers>
<!--CRLF-->
9: </add>
<!--CRLF-->
10: <add property="Message" value="yyy" name="filter2" typeConverter="System.ComponentModel.TypeConverter,System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<!--CRLF-->
11: <exceptionHandlers>
<!--CRLF-->
12: <add exceptionMessage="Baz" exceptionMessageResourceType=""
<!--CRLF-->
13: replaceExceptionType="Artech.CustomExceptionHandlers.BazException,Artech.CustomExceptionHandlers.Demo"
<!--CRLF-->
14: type="Microsoft.Practices.EnterpriseLibrary.ExceptionHandling.ReplaceHandler, Microsoft.Practices.EnterpriseLibrary.ExceptionHandling, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
<!--CRLF-->
15: name="Replace Handler" />
<!--CRLF-->
16: </exceptionHandlers>
<!--CRLF-->
17: </add>
<!--CRLF-->
18: </filters>
<!--CRLF-->
四、如何创建如何创建FilterableExceptionHandler
对配置有一个初步了解后,我们来定义FilterableExceptionHandlerData:
1: using Microsoft.Practices.EnterpriseLibrary.ExceptionHandling.Configuration;
<!--CRLF-->
2: using Microsoft.Practices.EnterpriseLibrary.Common.Configuration;
<!--CRLF-->
3: using System.Configuration;
<!--CRLF-->
4: using Microsoft.Practices.EnterpriseLibrary.Common.Configuration.ObjectBuilder;
<!--CRLF-->
5: namespace Artech.ExceptionHandlers
<!--CRLF-->
6: {
<!--CRLF-->
7: [Assembler(typeof(FilterableExceptionHandlerAssembler))]
<!--CRLF-->
8: public class FilterableExceptionHandlerData:ExceptionHandlerData
<!--CRLF-->
9: {
<!--CRLF-->
10: [ConfigurationProperty("filters", IsRequired = true)]
<!--CRLF-->
11: public NamedElementCollection<FilterEntry> Filters
<!--CRLF-->
12: {
<!--CRLF-->
13: get
<!--CRLF-->
14: {
<!--CRLF-->
15: return base["filters"] as NamedElementCollection<FilterEntry>;
<!--CRLF-->
border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height:
分享到:
相关推荐
《xser_exception_handler:PHP框架中的自定义异常处理机制解析》 在PHP开发过程中,异常处理是不可或缺的一部分,它能够帮助我们优雅地处理程序运行时出现的问题,避免程序崩溃并提供有用的错误信息。"xser_...
在"HandlerLooperDemo"这个示例项目中,开发者可能创建了一个自定义的Handler类,定义了处理消息的逻辑。同时,可能在另一个线程中启动了Looper,并使用这个Handler发送Message。通过这种方式,开发者可以演示如何在...
为了自定义异常处理逻辑,我们可以创建一个实现`ResponseErrorHandler`接口的类。这样,当`RestTemplate`遇到错误响应时,会调用我们自定义的异常处理方法,而不是直接抛出默认异常。 例如,我们可以创建一个名为`...
本主题将深入探讨自定义Handler、Looper、MessageQueue和Message类,帮助开发者更好地理解Android的Handler机制。 首先,我们来了解一下`Handler`。`Handler`是Android中用于发送和处理消息的核心类。它允许开发者...
Struts2作为一款流行的Java Web框架,其异常处理机制是其核心功能之一,它使得开发者能够优雅地管理和处理应用程序中的异常情况,提供了一种统一的错误处理方式,从而提高用户体验并增强程序的健壮性。 在Struts2...
**Exception Handler**: 异常处理器是程序中的一段代码,负责捕获和处理运行时发生的异常。在Windows操作系统中,异常处理器可以是自定义的或者由系统提供的。当异常发生时,异常处理器能够决定如何响应,例如恢复...
自定义异常是Java提供的一种机制,允许开发者创建特定于应用程序的异常类,以更精确地控制错误处理流程。本实例将深入探讨如何在Java中自定义异常。 首先,自定义异常通常继承自Java内置的`Exception`类或其子类,...
3. **`Handler`与`Looper`的关联**:当创建一个`Handler`对象时,其构造方法会获取当前线程中的`Looper`实例,并与之建立关联。这意味着,一旦创建了`Handler`对象,它就能够访问该线程的`MessageQueue`,并通过`...
每个异常处理表项`exception_handler_info`结构都代表了一个由当前方法定义的`catch`或`finally`块的信息。这些表项记录了处理异常的具体细节,包括异常的类型、处理代码的起始位置以及跳转的目标位置等。 具体而言...
在C++编程中,异常处理是一项关键的错误处理机制,它允许程序员在程序运行时捕获和处理意外的情况。本文将深入探讨C++中的标准异常处理(Standard Exception Handling, SEH)以及在Visual Studio(VS)环境下特有的...
以下是一个示例代码片段,展示了如何创建一个自定义的异常处理类`JsonExceptionHandler`: ```java package com.cxytiandi.gateway.exception; import java.util.HashMap; import java.util.Map; import org....
结构化异常处理(Structured Exception Handling,SEH)是Win32操作系统中的一个重要特性,用于处理程序执行过程中的异常情况。虽然通常与特定的编译器(如Microsoft的Visual C++或Borland C++)的运行时库相关联,...
MySQL中的异常处理是数据库编程中不可或缺的一部分,它允许开发者预设对可能出现的错误或异常的响应,从而确保程序的稳定性和健壮性。在MySQL中,异常定义和处理主要是通过`DECLARE`语句来实现的。 1. **异常定义**...
在filter中获取后端服务器返回来的数据,处理完后,创建子请求转发到另外一个服务器处理,接收服务器回应数据,再发送回给客户端。 5.支持自定义变量的注册与获取,在location中解析到对应的变量时,动态获取到...
本文将深入探讨在一个Activity中如何管理和处理多个Handler以及它们的消息流程。 首先,Handler是Android中的一个关键组件,它允许我们通过Message对象在不同的线程之间传递数据和执行任务。通常,我们在主线程(UI...
`Laravel JSON-aware Exception Handler` 是一个针对JSON API应用优化的异常处理器,它增强了Laravel默认异常处理机制,特别关注于返回JSON格式的错误响应。 Laravel的异常处理主要通过`Handler`类来实现,这个类...
Handler异步消息处理机制在Android开发中扮演着重要的角色,特别是在处理UI更新和与主线程交互时。在“Handler异步加载图片 GridView 上拉刷新 下拉刷新”这个主题中,我们将深入探讨如何利用Handler实现图片的异步...
Android Handler机制解析 Android Handler机制是Android系统中的一种机制,用于处理线程之间的通信和消息传递。在Android系统中,Handler机制是基于Java的线程机制来实现的。下面将对Android Handler机制进行详细的...
在Laravel框架中,`exception_handler`是处理应用程序中出现异常的关键组件。它是一个自定义错误处理器,允许开发者优雅地捕获、记录和响应错误,确保应用在遇到问题时仍能提供良好的用户体验。本篇文章将深入探讨...