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

时间:2022-09-17 18:31:58

回到目录

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

本文主要内容点

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

目录结构

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

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", );

一个日志拦截器

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

  /// <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的更多相关文章

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

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

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

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

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

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

  4. Lind&period;DDD&period;API核心技术分享

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

  5. Lind&period;DDD&period;Plugins~插件模式的集成

    回到目录 对于Lind.DDD这个敏捷框架来说,插件也是其中的一个亮点,所有被认为是插件(Plugins)的模块都会继承自IPlugins这个标示接口,它在程序启动时会找到所有插件,并通过autofa ...

  6. Lind&period;DDD&period;SSO单点登陆组件的使用&lpar;原创&rpar;

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

  7. Redis学习笔记~Redis事务机制与Lind&period;DDD&period;Repositories&period;Redis事务机制的实现

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

  8. Lind&period;DDD~实体属性变更追踪器的实现

    回到目录 看着这个标题很复杂,大叔把它拆开说一下,实体属性-变更-追踪器,把它拆成三部分大家看起来就容易懂一些了,实体属性:领域实体里有自己的属性,属性有getter,setter块,用来返回和设置属 ...

  9. Lind&period;DDD&period;Repositories&period;EF层介绍

    回到目录 Lind.DDD.Repositories.EF以下简称Repositories.EF,之所以把它从Lind.DDD中拿出来,完全出于可插拔的考虑,让大家都能休会到IoC的魅力,用到哪种方法 ...

随机推荐

  1. wp8 入门到精通 线程

    Dispatcher.BeginInvoke(() => MessageBox.Show(String.Format("A push notification {0} error oc ...

  2. Linux下更新瑞芯微固件

    有这样的需求,是因为提供的BSP中是在windows下烧写的系统.我直接在linux下开发,每次编译后代码都要在windows下烧写,是一个很麻烦的事情.为了解决这个问题我尝试着用VirtualBox ...

  3. 利用Django进行Web开发

    Web就是用来表示Internet主机上供外界访问的资源的.网页也统称为web资源.Internet上供外界访问的Web资源主要分为如下两类: 静态web资源:指web页面*人们浏览的数据始终是不变 ...

  4. 【模拟】&lbrack;NOIP2014&rsqb;螺旋矩阵&lbrack;c&plus;&plus;&rsqb;

    题目描述 一个n行n列的螺旋矩阵可由如下方法生成: 从矩阵的左上角(第1行第1列)出发,初始时向右移动:如果前方是未曾经过的格子,则继续前进,否则右转:重复上述操作直至经过矩阵中所有格子.根据经过顺序 ...

  5. Java学习笔记之——常用快捷键(eclipse)

    * Ctrl+C 复制 * Ctrl+V 粘贴 * Ctrl+A 全选 * Ctrl+S 保存 * Ctrl+Z 撤销 * Ctrl+Y 还原 * Ctrl+X 剪切 * Ctrl+F   查找 * ...

  6. xcode Xcode&lowbar;9&period;2&period;xip 官方离线下载地址

    一.打开下面的链接 https://developer.apple.com/downloads/ 二.在左侧搜索框中搜索:xcode 三.展开你要下载的版本,点列表右边的蓝色链接如:Xcode 9.2 ...

  7. linux内核完全剖析——基于0&period;12内核-笔记(2)-统一编址和独立编址

    IO是什么 ? IO(Input and Output)是输入输出接口.是CPU和其他外部设备(如串口.LCD.触摸屏.LED等)之间通信的接口.一般的,我们说的IO就是指CPU的各种内部或外部外设. ...

  8. 杂谈---小故事小道理,面试中的小技巧(NO&period;2)

    本篇是接着上一篇面试随笔的,上一次有猿友反应写的有些“扯淡”,LZ思来想去最大的原因可能是由于上一章写的全是一些大忌,既然是大忌,那么在现实当中发生的概率还是相对较小的,大部分人还是很少在面试中犯如此 ...

  9. 第三百九十一节,Django&plus;Xadmin打造上线标准的在线教育平台—404,403,500页面配置

    第三百九十一节,Django+Xadmin打造上线标准的在线教育平台—404,403,500页面配置 路由映射在全局也就是根目录里的urls.py里配置404路由映射 注意:不是写在urlpatter ...

  10. Oracle管理监控之linux下wendba登录设置

    [root@localhost ~]# su - oracle [oracle@localhost ~]$ which jar/usr/bin/jar [oracle@localhost ~]$ ex ...