zoukankan      html  css  js  c++  java
  • 从抽象谈起(三):AOP编程和ASP.NET MVC

    AOP(Aspect oriented programming)面向切面编程。说成切面不容易理解,代码哪里有切面?又不是三维物体。概念不管,我们从其思想来理解这个名词吧。 AOP的主要思想是把相同、相似的并且零散的逻辑抽离出来,统一处理;这样不仅维护起来方便,也让代码更加关注自己本身,清晰明了。

    比如我们常见的权限检查、日志记录、异常处理等都是散乱在系统各个地方,比如发表一篇文章的代码:

    1. public void Post(Article article)  
    2. {  
    3.     if(currentUser is null)  
    4.         throw new AuthException("您还没有登录");  
    5.     else  
    6.         ArticleManager.Save(article);  
    7. }  

    本来一句话ArticleManager.Save就能搞定的事情,现在要加上if else 还要处理异常,代码显得异常难看也难以维护。假如换成

    1. [Authorize]  
    2. public void Post(Article article)  
    3. {  
    4.     ArticleManager.Save(article);  
    5. }  

    用AuthroizeAttribute来处理权限问题,这样代码清晰很多,而且可以复用这个Attribute,这么好的思想就是AOP思想。
    当然Attribute只是一种实现方式,Attribute也是调用Post方法前,通过反射得到Attribute,然后执行其代码,
    平时我们用的最多的AOP就在ASP.NET MVC框架里,这个AuthorizeAttribute就是MVC自带的。我们可以重写他的一些方法达到自己想要的功能(比如权限等级等)。

    再举一个处理异常的例子,如果我们有一个统一的处理异常的逻辑,那么就可以在逻辑代码里不用try/catch,而是直接throw exception,这会让代码更加整洁。
    (PS:比不是说有了统一处理就再也不用try/catch了,有些异常该吃掉的还是要吃掉,这要看具体的业务需求。另外捕获不到的异常比如线程里的要注意catch。)
    比如例子:

    1. public void Post(Article article)  
    2. {  
    3.     if(String.IsNullOrEmpty(article.Title))  
    4.     {  
    5.         throw new ArgumentMissException("title");  
    6.     }  
    7.     ...  
    8.     ArticleManager.Save(article);  
    9. }  
    10.   
    11. protected override void OnException(ExceptionContext filterContext)  
    12. {  
    13.     //..异常处理代码  
    14. }  

    而只要重写MVC提供好的OnException方法就能处理所有的异常,或者是展现给用户友好的错误界面,或者是发送异常日志都很方便,而不用在每个地方都写处理的代码。
    延伸考虑一下,如果统一处理异常信息,那么对异常的善后处理的把握就要看异常类的设计和运用了。

    另外,再看上面的代码,如果有多个地方需要Post(Article),但又完全不一致,可是字段检查是一致的,那就会造成字段检查的代码重复,这种情况要么用一个单独的方法来验证Article的有效性,然后各个地方调用,要么就用MVC提供的ModelBinder,这也是通过参数的Attribute来实现的AOP方法;MVC考虑的太周到了,不得不赞。

    1. public void Post([ArticleBinder]Article article)  
    2. {  
    3.     //这里就不需要再写关于Article的验证代码了  
    4.     ArticleManager.Save(article);  
    5. }  
    6.   
    7. public class ArticleBinderAttribute : CustomModelBinderAttribute  
    8. {  
    9.     class ArticleBinder : IModelBinder  
    10.     {  
    11.         public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)  
    12.         {  
    13.             //虽然自定义了binder很惬意,但这里获取参数值时就没有用Action的参数那么舒服了。  
    14.             var title = controllerContext.RouteData.Values["title"].ToString();  
    15.             if (string.IsNullOrEmpty(title))  
    16.             {  
    17.                 throw new ArgumentNullException("title");  
    18.             }  
    19.             return new Article  
    20.             {  
    21.                 Title = title  
    22.             };  
    23.         }  
    24.     }  
    25.   
    26.     public override System.Web.Mvc.IModelBinder GetBinder()  
    27.     {  
    28.         return new ArticleBinder();  
    29.     }  
    30. }  

      

    运用框架提供的AOP很简单也很惬意,但我们在用别人的框架时不能只做应用级程序员,我们要领会其思想,掌握其本质,明白其实现。
    所幸,MVC是开源的,我们可以看他的源代码,关注提供AOP的地方。

    代码的设计或者说框架的设计,总是想让代码写起来干净利落,松耦合,不拖泥带水。
    所以清晰的设计就是从程序的开始,一步步规划其运行步骤,并在适当的地方提供一些供用户处理方法。框架就是把用户框在自己设定的圈子里,但又尽可能的给用户自由。
    我们看MVC的大致流程,
    1、从输入Url回车那一刻起,先是通过UrlRouting路由,来判断用户访问哪个Controller/Action;
    2、通过controllerfactory获取具体的controller实例,用户可自定义factory。
    3、通过actioninvoke调用action,在调用之前需要先获取action的filter,这些filter就是AOP的拦截器。用户都可以自定义各种filter(就是自定义的attribute)。
    4、根据执行顺序执行action和filter,onactionexecuting、onactionexecuted等。
    5、找到action对应的view,用户可自定义viewenginer。
    6、呈现页面结束。

    当出错的时候invoke的catch调用onexception的用户的实现。

    我本想罗列一些MVC的源码,但感觉没必要,有心人自己去下载看吧。如果不清楚的可以加群交流。


    就是这样简单,AOP的思想是想把和当前逻辑不相干的代码抽离的一种实现,我们如果追求代码的美感,就会更加在意整体代码的设计,AOP通常用于一个系统的外围搭建处。
    只有我们把架子、外围都搭建的漂亮,代码写起来才更美。

  • 相关阅读:
    css引入方式
    HTML标签
    动态导入模块impoerlib
    pymysql连接数据库
    创建数据库表之引擎
    IO多路复用互动聊天,select函数监听
    欧拉筛法求素数个数
    与三角形相关的问题 WITH 有向面积
    时间复杂度的计算
    折半查找
  • 原文地址:https://www.cnblogs.com/mad/p/3259664.html
Copyright © 2011-2022 走看看