从抽象谈起(三):AOP编程和ASP.NET MVC
AOP(Aspect oriented programming)面向切面编程。说成切面不容易理解,代码哪里有切面?又不是三维物体。概念不管,我们从其思想来理解这个名词吧。 AOP的主要思想是把相同、相似的并且零散的逻辑抽离出来,统一处理;这样不仅维护起来方便,也让代码更加关注自己本身,清晰明了。
比如我们常见的权限检查、日志记录、异常处理等都是散乱在系统各个地方,比如发表一篇文章的代码:
- public void Post(Article article)
- {
- if(currentUser is null)
- throw new AuthException("您还没有登录");
- else
- ArticleManager.Save(article);
- }
本来一句话ArticleManager.Save就能搞定的事情,现在要加上if else 还要处理异常,代码显得异常难看也难以维护。假如换成
- [Authorize]
- public void Post(Article article)
- {
- ArticleManager.Save(article);
- }
用AuthroizeAttribute来处理权限问题,这样代码清晰很多,而且可以复用这个Attribute,这么好的思想就是AOP思想。
当然Attribute只是一种实现方式,Attribute也是调用Post方法前,通过反射得到Attribute,然后执行其代码,
平时我们用的最多的AOP就在ASP.NET MVC框架里,这个AuthorizeAttribute就是MVC自带的。我们可以重写他的一些方法达到自己想要的功能(比如权限等级等)。
再举一个处理异常的例子,如果我们有一个统一的处理异常的逻辑,那么就可以在逻辑代码里不用try/catch,而是直接throw exception,这会让代码更加整洁。
(PS:比不是说有了统一处理就再也不用try/catch了,有些异常该吃掉的还是要吃掉,这要看具体的业务需求。另外捕获不到的异常比如线程里的要注意catch。)
比如例子:
- public void Post(Article article)
- {
- if(String.IsNullOrEmpty(article.Title))
- {
- throw new ArgumentMissException("title");
- }
- ...
- ArticleManager.Save(article);
- }
- protected override void OnException(ExceptionContext filterContext)
- {
- //..异常处理代码
- }
而只要重写MVC提供好的OnException方法就能处理所有的异常,或者是展现给用户友好的错误界面,或者是发送异常日志都很方便,而不用在每个地方都写处理的代码。
延伸考虑一下,如果统一处理异常信息,那么对异常的善后处理的把握就要看异常类的设计和运用了。
另外,再看上面的代码,如果有多个地方需要Post(Article),但又完全不一致,可是字段检查是一致的,那就会造成字段检查的代码重复,这种情况要么用一个单独的方法来验证Article的有效性,然后各个地方调用,要么就用MVC提供的ModelBinder,这也是通过参数的Attribute来实现的AOP方法;MVC考虑的太周到了,不得不赞。
- public void Post([ArticleBinder]Article article)
- {
- //这里就不需要再写关于Article的验证代码了
- ArticleManager.Save(article);
- }
- public class ArticleBinderAttribute : CustomModelBinderAttribute
- {
- class ArticleBinder : IModelBinder
- {
- public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
- {
- //虽然自定义了binder很惬意,但这里获取参数值时就没有用Action的参数那么舒服了。
- var title = controllerContext.RouteData.Values["title"].ToString();
- if (string.IsNullOrEmpty(title))
- {
- throw new ArgumentNullException("title");
- }
- return new Article
- {
- Title = title
- };
- }
- }
- public override System.Web.Mvc.IModelBinder GetBinder()
- {
- return new ArticleBinder();
- }
- }
运用框架提供的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通常用于一个系统的外围搭建处。
只有我们把架子、外围都搭建的漂亮,代码写起来才更美。
从抽象谈起(三):AOP编程和ASP.NET MVC的更多相关文章
- AOP编程和ASP.NET MVC
AOP编程和ASP.NET MVC AOP(Aspect oriented programming)面向切面编程.说成切面不容易理解,代码哪里有切面?又不是三维物体.概念不管,我们从其思想来理解这个名 ...
- C# 6 与 .NET Core 1.0 高级编程 - 41 ASP.NET MVC(中)
译文,个人原创,转载请注明出处(C# 6 与 .NET Core 1.0 高级编程 - 41 ASP.NET MVC(中)),不对的地方欢迎指出与交流. 章节出自<Professional C# ...
- C# 6 与 .NET Core 1.0 高级编程 - 41 ASP.NET MVC(上)
译文,个人原创,转载请注明出处(C# 6 与 .NET Core 1.0 高级编程 - 41 ASP.NET MVC(上)),不对的地方欢迎指出与交流. 章节出自<Professional C# ...
- C# 6 与 .NET Core 1.0 高级编程 - 41 ASP.NET MVC(下)
译文,个人原创,转载请注明出处(C# 6 与 .NET Core 1.0 高级编程 - 41 ASP.NET MVC(下)),不对的地方欢迎指出与交流. 章节出自<Professional C# ...
- 浅谈C#关于AOP编程的学习总结
难得在这样一个节日里给写出一篇博客,却没有佳人相约,没办法,这就是一个程(dan)序(shen)猿(gou)的真实生活情景,每天除了coding还是coding.唉..污染各位看官的眼了.好吧,进入正 ...
- ASP.NET MVC下的四种验证编程方式[续篇]
在<ASP.NET MVC下的四种验证编程方式>一文中我们介绍了ASP.NET MVC支持的四种服务端验证的编程方式("手工验证"."标注Validation ...
- 在.NET Core中三种实现“可插拔”AOP编程方式(附源码)
一看标题肯定会联想到使用动态编织的方式实现AOP编程,不过这不是作者本文讨论的重点. 本文讨论另外三种在netcore中可实现的方式,Filter(过滤器,严格意义上它算是AOP方式),Dynamic ...
- Spring AOP编程(二)-AOP实现的三种方式
AOP的实现有三种方式: l aop底层将采用代理机制进行实现. l 接口 + 实现类 :spring采用 jdk 的动态代理Proxy. l 实现类: ...
- 【原】iOS动态性(三) Method Swizzling以及AOP编程:在运行时进行代码注入
概述 今天我们主要讨论iOS runtime中的一种黑色技术,称为Method Swizzling.字面上理解Method Swizzling可能比较晦涩难懂,毕竟不是中文,不过你可以理解为“移花接木 ...
随机推荐
- 用c#开发微信 (17) 微活动 3 投票活动 (文本投票)
前面介绍了微活动<大转盘> 和 <刮刮卡>,这次介绍下微投票,微投票分二种,一种是文本投票, 一种是图片投票. 下面介绍文本投票的详细步骤: 1. 新建文本投票活动 ...
- Flash矢量图与位图性能对比
Flash中使用位图的性能要高于矢量图,究竟有多大区别呢?数据有最好的说服力,开始测试: 一.机器配置 二.测试过程 测试程序控制红色小球在舞台中不停匀速移动,通过改变小球数量控制实际帧率在24帧/秒 ...
- MySQL SELECT执行顺序
SELECT语句的完整语法为: () SELECT () DISTINCT <select_list> () FROM <left_table> () <join_typ ...
- js获取url传递参数
<head> <meta charset="UTF-8"> <title></title> <script type=&quo ...
- get请求的最大字符长度
各浏览器HTTP Get请求URL最大长度并不相同,几类常用浏览器最大长度及超过最大长度后提交情况如下: IE6.0 :url最大长度2083个字符,超过最大长度后无法提 ...
- Javascript构造函数与prototype
构造函数 构造函数的缺点 prototype的引入 Prototype模式的验证方法 构造函数 在Javascript语言中,new命令后面跟的不是类,而是构造函数(constructor). 构造函 ...
- Git版本工具的使用
Git版本工具:Git是一个开源的分布式版本控制系统,可用于敏捷高效的处理任何或大或小的项目.详细介绍地址:https://git-scm.com/downloads.今天主要为大家分享一下怎样把本地 ...
- no sigar-amd64-winnt.dll in java.library.path 错误
需要维护别人写的一个WEB项目,还原数据库,从SVN中检出源码,运行,提示如下错误: 5526 [localhost-startStop-1] DEBUG Sigar - no sigar-amd6 ...
- SQL行转列和列转行
行列互转,是一个经常遇到的需求.实现的方法,有case when方式和2005之后的内置pivot和unpivot方法来实现. 在读了技术内幕那一节后,虽说这些解决方案早就用过了,却没有系统性的认识和 ...
- c#之第一课入门
这几天看到微软的build大会,感觉微软不甘落后他人,曾经的巨头难道又要重新崛起,不管了,为了以后的饭碗,还是简单学习一些c#吧,有时这种紧张感不错的,现在由于这种紧张感,我已经掌握的java(主要弄 ...