EsbAOP应用--异常关闭器-阿里云开发者社区

开发者社区> zhuweisky> 正文

EsbAOP应用--异常关闭器

简介: 以我自己的异常处理经验,我通常会在UI事件处理函数或线程启动函数中截获所有的异常,然后对截获的异常作特定的处理--很多情况下,是显示一个错误信息给用户,或记录异常日志!在这“很多情况下”,我都需要做相同的工作,首先是用try...catch把UI事件处理函数或线程启动函数中的所有代码围起来,然后,可能就是MessageBox.Show(ex.Message)或其它的处理。
+关注继续查看

    以我自己的异常处理经验,我通常会在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() ;
        }

     大家可以仿照上面的例子自己写一个,看看运行的结果,下面也给出示例源码下载!

    示例下载

 

 

版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

相关文章
Spring 通过来AOP 实现前置,环绕,异常通知,注解(转)
本节主要内容:     1. Spring AOP前置通知案例     2. Spring AOP环绕通知案例     3. Spring AOP异常通知案例     4. Spring AOP注解使用案例   AOP是Aspect Oriented Programming的缩写,意思是面向方面...
1712 0
转:JavaScript事件冒泡简介及应用
(本文转载自别处) JavaScript事件冒泡简介及应用   一、什么是事件冒泡 在一个对象上触发某类事件(比如单击onclick事件),如果此对象定义了此事件的处理程序,那么此事件就会调用这个处理程序,如果没有定义此事件处理程序或者事件返回true,那么这个事件会向这个对象的父级对象传播,从里到外,直至它被处理(父级对象所有同类事件都将被激活),或者它到达了对象层次的最顶层,即document对象(有些浏览器是window)。
702 0
基于spring注解AOP的异常处理
一、前言   项目刚刚开发的时候,并没有做好充足的准备。开发到一定程度的时候才会想到还有一些问题没有解决。就比如今天我要说的一个问题:异常的处理。写程序的时候一般都会通过try...catch...finally对异常进行处理,但是我们真的能在写程序的时候处理掉所有可能发生的异常吗? 以及发生异常的时候执行什么逻辑,返回什么提示信息,跳转到什么页面,这些都是要考虑到的。
863 0
WPF关闭应用程序方法
原文:WPF关闭应用程序方法  很多人认为关闭应用程序应该很简单,例如WindowsForm里一个Application.Exit();方法就可以解决问题,但在WPF里面可别滥用,因为WPF里Application类没有该方法,倒是有一个Exit的事件驱动,在WPF应用程序里面关闭程序讲究很多: ...
867 0
Web系统下Office文档的处理 之OpenXml应用分类资料
本文对常见的处理参考和工具提供一个简要的参考。 对于实际的解决方案参考如下地址(有很多的分类知识) http://blogs.msdn.com/b/ericwhite/archive/2008/10/20/eric-white-s-blog-s-table-of-contents.
937 0
Android关闭应用中的所有Activity(一)
BaseActivity如下: package cc.c; import android.app.Activity; import android.
635 0
【高并发】由InterruptedException异常引发的思考
InterruptedException异常可能没你想的那么简单!
21 0
Android关闭应用中的所有Activity(二)
BaseActivity如下: package cn.testmanageactivity; import android.app.Activity; import android.
557 0
《C++语言基础》实践参考——平方根中的异常
返回:贺老师课程教学链接 项目要求 【项目1-平方根中的异常】 编写一个程序,求输入数的平方根。设置异常处理,当输入负数时采用异常处理机制给出提示。 [参考解答] #include&lt;iostream&gt; #include&lt;cmath&gt; using namespace std; double squareroot(double &amp;a
767 0
+关注
zhuweisky
从事软件开发行业十多年,专注于网络通信技术和网络语音视频技术,擅长系统架构设计、系统性能优化等。zhuweisky.cnblogs.com
300
文章
0
问答
文章排行榜
最热
最新
相关电子书
更多
《Nacos架构&原理》
立即下载
《看见新力量:二》电子书
立即下载
云上自动化运维(CloudOps)白皮书
立即下载