一起谈.NET技术,利用AOP重构代码

  AOP是什么?  
  AOP是OOP的延续,Aspect Oriented Programming的缩写,即面向方面编程。AOP是GoF设计模式的延续,设计模式追求的是调用者和被调用者之间的解耦,AOP也是这种目标的一 种实现。  
  案例:在应用程序中,我们经常会对某一段程序做异常处理,或者是把一个方法的调用所消耗的时间体现在日志中,如果我们对每个方法都写具体的实现,我想并不是一件轻松的事情。对于异常处理来讲,其实我们平常编程很少去捕获具体的异常,当然特殊程序除外,例如客户端捕获WCF异常时最好捕获CommunicationException,TimeoutException,Exception。否则一般都会直接捕获Exception,因为很多异常往往是意料之外的异常。对于记录方法调用时间问题,我想也非常麻烦,下面例子简单的展示了记录时间:当你需要对多个方法都需要记录时间时,这些代码往往让人感觉有重构的必要。

 

Stopwatch sw = new Stopwatch();
   sw.Start();
   //方法执行.....
   sw.Stop();
   WebLog.SquareLog.CommonLogger.Error("取积分广场首页酒店数据用时:"+sw.ElapsedMilliseconds .ToString ()+"毫秒");

 

      上面的记录方法调用用时,如果抽象出来,其实有下列特性:
      1:不是具体访问类的首要或主要功能,访问类主要功能是业务逻辑处理。
      2:具体访问类的主要功能可以独立、区分开来的。
      3:是这个系统的一个纵向切面,涉及多个类、多个类的方法。示意图如下:
 
     

 

      aspect:  新的程序结构关注系统的纵向切面,例如这里的异常处理以及方法调用时间记录,这个新的程序结构就是aspect(方面),方面(aspect)应该有以下职责:提供一些必备的功能,对被访问对象实现特有功能,以保证所以方法在被执行时都能正常的执行异常处理或者是其它的功能。

      AOP应用范围
      1:Authentication 权限
      2:Error handling 错误处理
      3:logging, tracing, profiling and monitoring 记录跟踪 优化 校准
      ......

     AOP具体实现:主要是利用泛型委托来实现AOP思想。但泛型委托有一个局限就是最多支持四个参数,当你的方法超过四个时就不太好应用AOP重构了。我最近分析了有以下三个地方我们可以对代码进行优化:

  第一:普通方法异常处理:ErrorHandler类,实现类参考第二或者是第三。

    客户端调用:

代码

string ErrorMethodText="取积分广场首页酒店数据异常:";
           list = ErrorWCFHandler .Invoke<ISearchHotelForSquare, List<HotelGenericInfo>>(cli, proxy => proxy.GetHotelGenericListForSquare(requestInfo).ToList() ); 

 
  第二:客户端调用WCF的异常处理:ErrorWCFHandler。

    代码:

代码

public  class ErrorWCFHandler
    {
       public static void Invoke<TContract>(TContract proxy, Action<TContract> action, string MethodElapsedTimeText, string MethodErrorText)
        {
            Stopwatch sw = new Stopwatch();
            sw.Start();
            try
            {
                action(proxy);
                (proxy as ICommunicationObject).Close();
            }
            catch (CommunicationException ex)
            {
                (proxy as ICommunicationObject).Abort();
                //Handle Exception             
                //throw;
                WebLog.SquareLog.CommonLogger.Error(MethodErrorText + ex.ToString());
            }
            catch (TimeoutException ex)
            {
                (proxy as ICommunicationObject).Abort();
                //Handle Exception         
                //throw;
                WebLog.SquareLog.CommonLogger.Error(MethodErrorText + ex.ToString());
            }
            catch (Exception ex)
            {
                //Handle Exception        
                //(proxy as ICommunicationObject).Close();      
                WebLog.SquareLog.CommonLogger.Error(MethodErrorText + ex.ToString());
            }
            sw.Stop();

            WebLog.SquareLog.CommonLogger.Error(MethodElapsedTimeText + sw.ElapsedMilliseconds.ToString() + "毫秒");
        }
       public static TReturn Invoke<TContract, TReturn>(TContract proxy, Func<TContract, TReturn> func, string MethodElapsedTimeText, string MethodErrorText)
        {
            Stopwatch sw = new Stopwatch();
            sw.Start();
            TReturn returnValue = default(TReturn);
            try
            {
                returnValue = func(proxy);
            }
            catch (CommunicationException ex)
            {
                (proxy as ICommunicationObject).Abort();
                //Handle Exception     
                //throw;
                WebLog.SquareLog.CommonLogger.Error(MethodErrorText + ex.ToString());
            }
            catch (TimeoutException ex)
            {
                (proxy as ICommunicationObject).Abort();
                //Handle Exception       
                //throw;
                WebLog.SquareLog.CommonLogger.Error(MethodErrorText + ex.ToString());
            }
            catch (Exception ex)
            {
                //Handle Exception  
                WebLog.SquareLog.CommonLogger.Error(MethodErrorText + ex.ToString());
            }
            sw.Stop();

            WebLog.SquareLog.CommonLogger.Error(MethodElapsedTimeText + sw.ElapsedMilliseconds.ToString() + "毫秒");
            return returnValue;
        }
    }

    客户端调用:         

代码

string ComputationTimeText="取积分广场首页酒店数据耗时:";
           string ErrorMethodText="取积分广场首页酒店数据异常:";
           list = ErrorWCFHandler .Invoke<ISearchHotelForSquare, List<HotelGenericInfo>>(cli, proxy => proxy.GetHotelGenericListForSquare(requestInfo).ToList

(),ComputationTimeText ,ErrorMethodText );  

  第三:记录方法调用时间,这中间也增加了异常处理:ErrorAndComputationTimeHandler

    代码:

代码

 public class ErrorAndComputationTimeHandler
    {
        public static void Invoke<TContract>(TContract proxy, Action<TContract> action, string MethodElapsedTimeText,string MethodErrorText)
        {
            Stopwatch sw = new Stopwatch();
            sw.Start();
            try
            {
                action(proxy);

            }
            catch (Exception ex)
            {
                //Handle Exception   
                WebLog.SquareLog.CommonLogger.Error(MethodErrorText + ex.ToString());

            }
            sw.Stop();

            WebLog.SquareLog.CommonLogger.Error(MethodElapsedTimeText  + sw.ElapsedMilliseconds.ToString() + "毫秒");
        }
        public static void Invoke<TContract, TContract2>(TContract proxy, TContract2 proxy2, Action<TContract, TContract2> action, string MethodElapsedTimeText,string MethodErrorText)
        {
            Stopwatch sw = new Stopwatch();
            sw.Start();
            try
            {
                action(proxy, proxy2);

            }
            catch (Exception ex)
            {
                //Handle Exception   
                WebLog.SquareLog.CommonLogger.Error(MethodErrorText + ex.ToString());

            }
            sw.Stop();

            WebLog.SquareLog.CommonLogger.Error(MethodElapsedTimeText  + sw.ElapsedMilliseconds.ToString() + "毫秒");
        }
        public static void Invoke<TContract, TContract2, TContract3>(TContract proxy, TContract2 proxy2, TContract3 proxy3, Action<TContract, TContract2, TContract3> action, string MethodElapsedTimeText,string MethodErrorText)
        {
            Stopwatch sw = new Stopwatch();
            sw.Start();
            try
            {
                action(proxy, proxy2, proxy3);

            }
            catch (Exception ex)
            {
                //Handle Exception   
                WebLog.SquareLog.CommonLogger.Error(MethodErrorText + ex.ToString());

            }
            sw.Stop();

            WebLog.SquareLog.CommonLogger.Error(MethodElapsedTimeText  + sw.ElapsedMilliseconds.ToString() + "毫秒");
        }
        public static void Invoke<TContract, TContract2, TContract3, TContract4>(TContract proxy, TContract2 proxy2, TContract3 proxy3, TContract4 proxy4, Action<TContract, TContract2, TContract3, TContract4> action,  string MethodElapsedTimeText,string MethodErrorText)
        {
            Stopwatch sw = new Stopwatch();
            sw.Start();
            try
            {
                action(proxy, proxy2, proxy3, proxy4);

            }
            catch (Exception ex)
            {
                //Handle Exception   
                WebLog.SquareLog.CommonLogger.Error(MethodErrorText + ex.ToString());

            }
            sw.Stop();

            WebLog.SquareLog.CommonLogger.Error(MethodElapsedTimeText  + sw.ElapsedMilliseconds.ToString() + "毫秒");
        }
        public static TReturn Invoke<TContract, TReturn>(TContract proxy, Func<TContract, TReturn> func,  string MethodElapsedTimeText,string MethodErrorText)
        {
            Stopwatch sw = new Stopwatch();
            sw.Start();
            TReturn returnValue = default(TReturn);
            try
            {
                returnValue = func(proxy);
            }
            catch (Exception ex)
            {
                //Handle Exception   
                WebLog.SquareLog.CommonLogger.Error(MethodErrorText + ex.ToString());

            }
            sw.Stop();

            WebLog.SquareLog.CommonLogger.Error(MethodElapsedTimeText  + sw.ElapsedMilliseconds.ToString() + "毫秒");
            return returnValue;
        }
        public static TReturn Invoke<TContract, TContract2, TReturn>(TContract proxy, TContract2 proxy2, Func<TContract, TContract2, TReturn> func,  string MethodElapsedTimeText,string MethodErrorText)
        {
            Stopwatch sw = new Stopwatch();
            sw.Start();
            TReturn returnValue = default(TReturn);
            try
            {
                returnValue = func(proxy, proxy2);
            }
            catch (Exception ex)
            {
                //Handle Exception   
                WebLog.SquareLog.CommonLogger.Error(MethodErrorText + ex.ToString());

            }
            sw.Stop();

            WebLog.SquareLog.CommonLogger.Error(MethodElapsedTimeText  + sw.ElapsedMilliseconds.ToString() + "毫秒");
            return returnValue;
        }
        public static TReturn Invoke<TContract, TContract2, TContract3, TReturn>(TContract proxy, TContract2 proxy2, TContract3 proxy3, Func<TContract, TContract2, TContract3, TReturn> func,  string MethodElapsedTimeText,string MethodErrorText)
        {
            Stopwatch sw = new Stopwatch();
            sw.Start();
            TReturn returnValue = default(TReturn);
            try
            {
                returnValue = func(proxy, proxy2, proxy3);
            }
            catch (Exception ex)
            {
                //Handle Exception   
                WebLog.SquareLog.CommonLogger.Error(MethodErrorText + ex.ToString());

            }
            sw.Stop();

            WebLog.SquareLog.CommonLogger.Error(MethodElapsedTimeText  + sw.ElapsedMilliseconds.ToString() + "毫秒");
            return returnValue;
        }
        public static TReturn Invoke<TContract, TContract2, TContract3, TContract4, TReturn>(TContract proxy, TContract2 proxy2, TContract3 proxy3, TContract4 proxy4, Func<TContract, TContract2, TContract3, TContract4, TReturn> func,  string MethodElapsedTimeText,string MethodErrorText)
        {
            Stopwatch sw = new Stopwatch();
            sw.Start();
            TReturn returnValue = default(TReturn);
            try
            {
                returnValue = func(proxy, proxy2, proxy3, proxy4);
            }
            catch (Exception ex)
            {
                //Handle Exception   
                WebLog.SquareLog.CommonLogger.Error(MethodErrorText + ex.ToString());

            }
            sw.Stop();
            WebLog.SquareLog.CommonLogger.Error(MethodElapsedTimeText  + sw.ElapsedMilliseconds.ToString() + "毫秒");
            return returnValue;
        }
    }

    客户端调用:     

代码

string ComputationTimeText = "取酒店是否在积分广场首页推荐数据耗时:";
            string ErrorMethodText = "取酒店是否在积分广场首页推荐数据异常:";
            string conn = WebConfig.DaoConfig.MisMasterDBReadConnectionString;
            HotelRecommendInfo = ErrorAndComputationTimeHandler.Invoke<HotelRequestInfo, string, List<HotelGenericInfo>>(requestInfo, conn, SearchRecommendHotelData, ComputationTimeText, ErrorMethodText);

  AOP的优势:

  1:上述应用范例在没有使用AOP情况下,也能解决,但是,AOP可以让我们从一个更高的抽象概念来理解软件系统。可以这么说:因为使用AOP结构,对于一个大型复杂系统来说可以简化不少代码。

  2:并不是所有的人都需要关心AOP,使得其它开发人员有更多精力去关注自己的业务逻辑。

时间: 2024-10-01 06:30:21

一起谈.NET技术,利用AOP重构代码的相关文章

利用AOP重构代码

AOP是什么? AOP是OOP的延续,Aspect Oriented Programming的缩写,即面向方面编程.AOP是GoF设计模式的延续,设计模式追求的是调用者和被调用者之间的解耦,AOP也是这种目标的一 种实现. 案例:在应用程序中,我们经常会对某一段程序做异常处理,或者是把一个方法的调用所消耗的时间体现在日志中,如果我们对每个方法都写具体的实现,我想并不是一件轻松的事情.对于异常处理来讲,其实我们平常编程很少去捕获具体的异常,当然特殊程序除外,例如客户端捕获WCF异常时最好捕获Com

一起谈.NET技术,使用VS2010代码分析功能增强ASP.NET应用程序安全

任何从事ASP.NET开发的人都不得不承认,在其职业生涯中曾经遇到过应用程序安全问题,开发人员常常被迫尽快交付代码,平台的复杂性和各种配置选项让应用程序的安全总达不到预期,此外,调试和生产环境的配置要求可能会不同,因此,一个常见的问题是将调试配置引入到生产环境,从而造成各种问题. 经过多年的发展,ASP.NET平台已经成熟,MSDN和社区博客也产生了大量优秀的文档,但确定使用哪些功能或配置往往是件麻烦事,即使开发人员有着良好的安全意识和安全技能,错误总是在所难免,程序中的漏洞仍然很多.同行代码审

一起谈.NET技术,一句代码实现批量数据绑定[上篇]

对于一个以数据处理为主的应用中的UI层,我们往往需要编写相当多的代码去实现数据绑定.如果界面上的控件和作为数据源的实体类型之间存储某种约定的映射关系,我们就可以实现批量的数据绑定.为了验证这种想法,我写了一个小小的组件.这个小玩意仅仅是我花了两个小时写的,其中还有很多问题没有解决,比如对于空值的处理,特殊控件属性值的HTML编码问题,以及频繁反射的性能问题,仅仅演示一种解决思路而已.本篇着重介绍如何通过这个组件来解决我们在进行数据绑定过程中的常见问题,下篇会介绍它的设计.[源代码从这里下载] 目

一起谈.NET技术,一句代码实现批量数据绑定[下篇]

<上篇>主要介绍如何通过DataBinder实现批量的数据绑定,以及如何解决常见的数据绑定问题,比如数据的格式化.接下来,我们主要来谈谈DataBinder的设计,看看它是如何做到将作为数据源实体的属性值绑定到界面对应的控件上的.此外,需要特别说明一点:<上篇>中提供了DataBinder最初版本的下载,但已经和本篇文章介绍的已经大不一样了. 最新版本的主要解决两个主要问题:通过Expression Tree的方式进行属性操作(属性赋值和取值),添加了"数据捕捉"

一起谈.NET技术,.Net语言中关于AOP 的实现详解

文章主要和大家讲解开发应用系统时在.Net语言中关于AOP 的实现.LogAspect完成的功能主要是将Advice与业务对象的方法建立映射,并将其添加到Advice集合中.由于我们在AOP实现中,利用了xml配置文件来配置PointCut,因此对于所有Aspect而言,这些操作都是相同的,只要定义了正确的配置文件,将其读入即可.对于Aspect的SyncProcessMessage(),由于拦截和织入的方法是一样的,不同的只是Advice的逻辑而已,因此在所有Aspect的公共基类中已经提供了

利用 aop 追踪 数据库连接池使用情况

问题描述 最近一个项目中使用了apache的dbcp 作数据库连接池,最近程序老发现报连接池耗尽.仔细查了代码,没有找到问题.所以想利用 aop 技术确定一下程序中是否有未释放的连接.想法是 看分配的连接和释放的连接是否对等.定义了两个切入点 1.execution(java.sql.Connection javax.sql.DataSource.getConnection()) 2. execution(void java.sql.Connection.close())程序运行时 第二个切入点

领导重构代码,重构一堆的bug,怎么办 ?

问题描述 领导重构代码,重构一堆的bug,怎么办 ? 本来测试通过领导重构代码,重构一堆的bug,页面都给换了?怎么办 解决方案 领导说什么就是什么,不要自作主张 解决方案二: 重构代码,有bug就修正呗.

Android(Java)利用findbugs进行代码静态检查

本文主要介绍利用java静态代码检查工具findbugs进行代码检查,包括其作用.安装.使用.高级功能(远程review和bug同步). 虽然Android提供了Test Project工程以及instrumentation可以方便的进行单元测试,不过据了解国内Android开发会写自测代码的寥寥无几.那么有没有简单的方法一定程度上保证代码质量呢.Android应用开发大多使用Java,所以对于Java代码检查工具都可以适用,本文介绍其中功能较为强大的findbugs. 1.findbugs作用

【视觉目标跟踪最高峰】VOT Challenge 2017 亚军北邮团队技术分享(附代码)

视觉跟踪领域国际顶级赛事 Visual-Object-Tracking Challenge (VOT) 2017年结果出炉,结合传统滤波及深度学习的方案取得最佳成绩.本文是第二名北京邮电大学代表团队的技术分享.他们基于滤波的框架,抛弃传统特征,只使用CNN特征,减少了特征冗余,缓解了模型过拟合,使追踪器在速度和精度上都有不小的提高.代码分享链接:https://github.com/he010103/CFWCR.git 随着深度学习在计算机视觉方面大放异彩,近几年物体追踪也得到了飞速的发展.物体