.Net MVC之所以发展的如些之好,一个很重要原因就是它公开了一组AOP的过滤器,即使用这些过滤器可以方便的拦截controller里的action,并注入我们自己的代码逻辑,向全局的异常记录,用户授权,Url授权,操作行为记录等,这一大批Lind的基本组件都是实现MVC和API的过滤实现的,使用这些过滤让我们不用去像HttpModule和HttpHandler那样,还要在Config里配置注入点,让程序员在开发方式上感觉很舒服,维护成功很低!

本文主要内容点

  1. Lind.DDD里的方法拦截器
  2. 动态注入需要Lind.DDD.Plugins的支持
  3. 零配置的方法拦截
  4. 一个日志拦截器
  5. 正在构建一个缓存拦截器

目录结构

Lind.DDD里的方法拦截器

Lind.DDD.Aspects这个拦截器起源自ABP框架,但不知道为什么,ABP对这个拦截器并没有完全实现,所以今天大叔又实现了一下,解决了相关BUG, 对方法拦截上,在动态代理工厂里对方法拦截上下文添加了一些必要的参数,因为大叔认为,你只提供一个“方法名称”参数,太过简单了,哈哈。

    /// <summary>/// 方法相关信息/// </summary>public class MethodMetadata{/// <summary>/// 上下文/// </summary>private MethodInfo _context;/// <summary>/// 方法名/// </summary>private string _methodName;public MethodMetadata(string methodName, MethodInfo context = null){_methodName = methodName;_context = context;}/// <summary>/// 方法名称/// </summary>public virtual string MethodName{get { return _methodName; }set { _methodName = value; }}/// <summary>/// 方法上下文/// </summary>public virtual string Context{get { return _context; }set { _context = value; }}}

一个简单的日志拦截器的实现,它在方法执行前去拦截

   /// <summary>/// 方法执行前拦截,并记录日志/// </summary>public class LoggerAspectAttribute : BeforeAspectAttribute{public override void Action(InvokeContext context){Console.WriteLine("logger start!" + context.Method.MethodName);Lind.DDD.Logger.LoggerFactory.Instance.Logger_Info(context.Method.MethodName + "这个方法开始执行");}}

而在程序中,这个特性Attribute如何被动态代理拦截呢,事件上,如果你直接写代码也是可以的,就是使用Aspect提供的ProxyFactory工厂来进行生产,但大叔认为,这样的代码耦合度太高,而且对于现有的代码还需要进行修改,最重要一点,这种代码总感觉有种坏味道!

     static void Main(string[] args){ProxyFactory.CreateProxy<ITest>(typeof(LoggerAspectTest)).Do();Console.Read();}

所以就有了下面大叔的封装,用到了Lind.DDD.Plugins这个插件模式,将所有的拦截器都先进行注册,然后在生产对象时为它动态添加对应的ProxyFactory对象,请大家接着向下看,动态注入需要Lind.DDD.Plugins的支持这部分讲解。

动态注入需要Lind.DDD.Plugins的支持

上面的拦截器只是简单的实现,简单的调用,而不具有一般性,即你需要自己维护需要“拦截的代码”,而大叔在进行使用中感觉很不爽,于是想起了Plugins,让插件为我们实现这种注入,就像MVC的Filter一样,在框架本身去实现方法拦截的功能!大叔认为这样才是最好的!

1 所有拦截器都继承IAspectProxy表示接口,而它自己则是继承IPlugins的

   /// <summary>/// 支持AOP拦截的接口,它被认为是一种插件动态注入到系统中/// </summary>public interface IAspectProxy : Lind.DDD.Plugins.IPlugins { }

2 在PluginManager的Resolve方法中,添加动态的ProxyFactory实现,让实现了IAspectProxy的类型,自动进行拦截器的实现

      /// <summary>/// 从插件容器里返回对象/// </summary>/// <param name="serviceName">对象全名</param>/// <param name="serviceType">接口类型</param>/// <returns></returns>public static object Resolve(string serviceName, Type serviceType){var obj = _container.ResolveNamed(serviceName, serviceType);if (typeof(Lind.DDD.Aspects.IAspectProxy).IsAssignableFrom(serviceType)){obj = ProxyFactory.CreateProxy(serviceType, obj.GetType());}return obj;}

OK,有了上面的代码,我们的方法拦截就成了一种插件了,在使用的时间之前的插件的使用方法相同,当然底层还是使用autofac来实现的Ioc容器。

 var old = Lind.DDD.Plugins.PluginManager.Resolve<IAopHelloTest2>("Lind.DDD.UnitTest.AopHello");old.Hello("zz", 1);

一个日志拦截器

日志记录是一些业务复杂方法必备的,如一些订单方法,用户提现方法都会添加相关的日志,而如果希望动态添加日志,而不在代码段中去添加,则可以设计一个日志拦截器,当然你可以在方法执行前去控制,也可以在方法执行后去控制!

  /// <summary>/// 方法执行前拦截,并记录日志/// </summary>public class LoggerAspectAttribute : BeforeAspectAttribute{public override void Action(InvokeContext context){Console.WriteLine("logger start!" + context.Method.MethodName);Lind.DDD.Logger.LoggerFactory.Instance.Logger_Info(context.Method.MethodName + "这个方法开始执行");}}/// <summary>/// 方法执行完成后拦截,并记录日志/// </summary>public class LoggerEndAspectAttribute : AfterAspectAttribute{public override void Action(InvokeContext context){Console.WriteLine("logger start!" + context.Method.MethodName);Lind.DDD.Logger.LoggerFactory.Instance.Logger_Info(context.Method.MethodName + "这个方法开始执行");}}

目录方法需要添加这种日志的行为,只要在方法上添加对应的特性即可,(方法不需要为虚方法)而不需要修改方法代码体,如下面的代码

   /// <summary>/// AOP调用方式/// </summary>public class LoggerAspectTest : ITest{[LoggerAspectAttribute]public void Do(){//我做事情Console.WriteLine("我做事情");}}

正在构建一个缓存拦截器

目前,大叔正在构建一个缓存的拦截器,主要是实现对方法返回值的缓存,而不需要将这种缓存判断的逻辑写在每个方法体内,大叔认为,这种面向切面的AOP的设计,才是大势所趋,敬请大家期待!

   /// <summary>/// 缓存拦截器/// </summary>public class CachingAspectAttribute : BeforeAspectAttribute{CachingMethod cachingMethod;public CachingAspectAttribute(CachingMethod cachingMethod){this.cachingMethod = cachingMethod;}public override void Action(InvokeContext context){var method = context.Method;string prefix = "Lind";var baseInterfaces = context.GetType().GetInterfaces();if (baseInterfaces != null && baseInterfaces.Any()){foreach (var item in baseInterfaces){prefix += item.ToString() + "_";}}//键名,在put和get时使用var key = prefix + method.MethodName;Console.WriteLine(key);switch (cachingMethod){case CachingMethod.Remove://……break;case CachingMethod.Get://……break;case CachingMethod.Put://……break;default:throw new InvalidOperationException("无效的缓存方式。");}}}

我们对支持的追求将不会停止,希望广大青年都可以踏一心来,去认真的研究一个技术,事实上,对一个技术研究透了,大叔认为就足够了!

此致

敬礼

本文转自博客园张占岭(仓储大叔)的博客,原文链接:Lind.DDD.Aspects通过Plugins实现方法的动态拦截~Lind里的AOP,如需转载请自行联系原博主。

Lind.DDD.Aspects通过Plugins实现方法的动态拦截~Lind里的AOP相关推荐

  1. Lind.DDD.LindAspects方法拦截的介绍

    回到目录 什么是LindAspects 之前写了关于Aspects的文章<Lind.DDD.Aspects通过Plugins实现方法的动态拦截~Lind里的AOP>,今天主要在设计思想上进 ...

  2. Lind.DDD敏捷领域驱动框架~介绍

    最近觉得自己的框架过于复杂,在实现开发使用中有些不爽,自己的朋友们也经常和我说,框架太麻烦了,要引用的类库太多:之前架构之所以这样设计,完全出于对职责分离和代码附复用的考虑,主要参考了微软的DDD大作 ...

  3. Lind.DDD敏捷领域驱动框架~Lind.DDD各层介绍

    回到目录 Lind.DDD项目主要面向敏捷,快速开发,领域驱动等,对于它的分层也是能合并的合并,比之前大叔的框架分层更粗糙一些,或者说更大胆一些,在开发人员使用上,可能会感觉更方便了,更益使用了,这就 ...

  4. Lind.DDD.API核心技术分享

    关于Lind.DDD框架里API框架的技术点说明 讲解:张占岭 花名:仓储大叔 主要框架:Lind.DDD 目录 关于Lind.DDD.Authorization 关于授权的原理 关于ApiValid ...

  5. Lind.DDD.DynamicModules动态模块化的设计

    回到目录 在Lind.DDD框架里有Module,主要用于全局自动添加的模块,它类似于ABP系统里的Module,但有时过于自动化了可能使系统太死板,而有时将需要的模块手动载入可能对我们更合适,所以大 ...

  6. Redis学习笔记~Redis事务机制与Lind.DDD.Repositories.Redis事务机制的实现

    回到目录 Redis本身支持事务,这就是SQL数据库有Transaction一样,而Redis的驱动也支持事务,这在ServiceStack.Redis就有所体现,它也是目前最受业界认可的Redis驱 ...

  7. Lind.DDD.Manage项目核心技术分享

    回到目录 关于Lind.DDD.Manager的培训与学习 讲解:张占岭 花名:仓储大叔 主要框架:Lind.DDD,Lind.DDD.Manager 关于Lind.DDD.Manager 由于数据模 ...

  8. 关于Lind.DDD.Api客户端的使用与知识分享

    回到目录 关于Lind.DDD.Api的使用与客户端的调用 作者:张占岭 花名:仓储大叔 框架:Lind.DDD,Lind.DDD.Api 目录 Api里注册全局校验特性 1 Api中设置全局的Cor ...

  9. Lind.DDD.SSO单点登陆组件的使用(原创)

    回到目录 一般sso的说明 在Lind.DDD框架里,有对单点登陆的集成,原理就是各个网站去sso网站统一登陆授权,之后在sso网站将登陆的token进行存储,存储方式随你(cache,redis,m ...

最新文章

  1. cad转换成png,svg
  2. MapWindow记录
  3. matlab 入门 mobi,振动力学基础与MATLAB应用
  4. pycharm导入(import)报红(出现红色波浪线)解决办法(Mark Directory as —— Sources Root)
  5. ros自己写避障算法_迷雾学术篇|视觉感知的无人机动态避障(下篇)
  6. 这几款前端必备构建工具合辑,我们帮你整理好了!
  7. 首次构建android studio gradle 下载缓慢的问题
  8. python tornado 工程范例
  9. 测试思路系列:《谷歌的软件测试之道》读书笔记
  10. 关于简历:怎样才叫熟悉/精通Linux?
  11. 经典Hello Word窗口表示,可视化编程入门。
  12. CentOS 7 配置 VNC 远程桌面连接
  13. lunix入侵别人电脑_记录一次Linux的实战入侵过程
  14. JavaEE初阶-计算机是如何工作的
  15. 检测出DNF服务器未响应,dnf老是卡死未响应
  16. Oxygen XML Editor(XML编辑器)v21.0专业破解版
  17. Rsync+实时监控同步软件
  18. BAPI_PO_CREATE1 创建采购订单
  19. 上一周,小白的我试着搭建了两个个人博客:在github和openshift上
  20. wps图表横纵坐标怎么设置_用WPS的excel插入图表怎样快速设置横纵坐标轴

热门文章

  1. 吴恩达机器学习 神经网络 作业1(用已经求好的权重进行手写数字分类) Python实现 代码详细解释
  2. java学生通讯录_Java实现XML文件学生通讯录
  3. python中依次输出字符_Python如何输出某关键字符并输出完整字符串
  4. python展示全部好友_利用Python网络爬虫抓取微信好友的签名及其可视化展示
  5. 若依单体项目定时任务模块使用教程
  6. airpods固件更新方法_AirPods 固件迎来大更新!这两个功能终于支持了
  7. TensorFlow 2快速入门之安装与测试
  8. CMS 平台: Drupal, eZ Publish, WordPress, CMS Made Simple 横向比较
  9. FTP 编写 4:命令解析
  10. centos7解压安装mysql_CentOS7 安装Mysql5.7 解压缩版