C#使用KingAOP实现AOP面向切面编程一
AOP面向切面编程(Aspect Oriented Programming),是通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术。
实现AOP主要由两种方式,一种是编译时静态植入,优点是效率高,缺点是缺乏灵活性,.net下PostSharp为代表者(这个是收费的)。
另一种方式是动态代理,优缺点与前者相反,动态为目标类型创建代理,通过代理调用实现拦截。
Spring框架用的核心技术就是AOP,是函数式编程的一种衍生范型。利用AOP的好处就是可以对业务逻辑进行隔离,降低耦合度,提高程序的可重用性,同时提高了开发的效率。
AOP在我理解来说就是一种编程思想和架构设计,AOP是OOP面向对象编程的延续,是软件开发中的一个热点。AOP的简称叫”面向切面“编程,即在现有的代码里横向的切分开来进行相应处理,比如说MVC里的刷选器(过滤器)。
AOP主要功能是将系统中非核心的公共业务提取出来,进行单独处理。比如日志记录、性能统计、安全控制、事务处理、异常处理等等。
AOP主要意图是将日志记录,性能统计,安全控制,事务处理,异常处理等代码从业务逻辑代码中划分出来,通过对这些行为的分离,我们希望可以将它们独立到非指导业务逻辑的方法中,进而改变这些行为的时候不影响业务逻辑的代码。
下面介绍一些.NET相关的AOP框架
1. PostSharp(编译时静态植入)是最有名且使用率较高的一个,但是在Nuget上的版本是需要付费的(2.0)以上都要付费。
2. Spring.Net 用于解决企业应用开发复杂性的一种容器框架,它实现了控制反转IOC和依赖注入DI,通俗解释就是通过spring.net框架的容器来创建对象实体,而不是通过程序员new出来,
降低程序对服务类的依赖性,提高软件的可扩展性。只要在spring.net的相应xml中配置节点,创建容器上下文后再通过配置获取对象就可以。
3. Autofac 是一个.net下非常优秀,性能非常好的IOC容器(.net下效率最高的容器),加上AOP简直是如虎添翼。Autofac的AOP是通过Castle(也是一个容器)项目的核心部分实现的,名为Autofac.Extras.DynamicProxy,
顾名思义其实现方式为动态代理。
4. Castle.Core 本质是创建继承原来类的代理类,重写虚方法实现AOP功能。
5. KingAOP 开源框架KingAOP是基于动态类型进行操作和绑定的。
个人推荐使用Castle.Core 或者 KingAOP
下面介绍一个比较精简的AOP框架:KingAOP 使用方式比较简单,如下顺序:
1、在Nuget上搜索KingAOP,如图:
或者通过命令安装:
Install-Package KingAOP
2、创建一个刷选器类(切面处理类),继承OnMethodBoundaryAspect,并重写相关的事件,如下代码:
/// <summary> /// 创建一个刷选器类(切面处理类) /// </summary> public class AopFilter : OnMethodBoundaryAspect { public override void OnEntry(MethodExecutionArgs args) { Console.WriteLine("call-------->AopFilter------>OnEntry"); base.OnEntry(args); } public override void OnException(MethodExecutionArgs args) { Console.WriteLine("call-------->AopFilter------>OnException"); base.OnException(args); } public override void OnSuccess(MethodExecutionArgs args) { Console.WriteLine("call-------->AopFilter------>OnSuccess"); base.OnSuccess(args); } public override void OnExit(MethodExecutionArgs args) { Console.WriteLine("call-------->AopFilter------>OnExit"); base.OnExit(args); } }
3、创建一个类,该类的方法注册上面新建的刷选器,如下代码:
/// <summary> /// 该类需要继承IDynamicMetaObjectProvider,因为KingAOP是基于动态类型进行操作和绑定的,如不继承是不会进入到刷选器中的相应事件里 /// </summary> public class SimonDemo : IDynamicMetaObjectProvider { public SimonDemo() { Console.WriteLine(" Call 'SimonDemo类' - 'Constructor(构造函数)'"); } [AopFilter] public void Operate() { Console.WriteLine("Call 'SimonDemo类' - 'Operate方法' "); } /// <summary> /// 该类必须实现IDynamicMetaObjectProvider的GetMetaObject方法 /// </summary> /// <param name="parameter"></param> /// <returns></returns> public DynamicMetaObject GetMetaObject(Expression parameter) { return new AspectWeaver(parameter, this); } }
上面的SimonDemo类需要继承IDynamicMetaObjectProvider,因为KingAOP是基于动态类型进行操作和绑定的,如不继承是不会进入到刷选器中的相应事件里。
该类必须实现IDynamicMetaObjectProvider的GetMetaObject方法,同时在需要切面的方法上用属性[AopFilter]进行标注,
同时,刷选器属性是限制了只能对应方法,且不包含构造函数;
4、接下来就是测试代码,如下
static void Main(string[] args) { //简单例子 Console.WriteLine("Call Main .."); //注意:如果需要用KingAop进行横向切面则必须在实例化被切面的类时用动态类型dynamic接收 dynamic simon = new SimonDemo(); simon.Operate(); Console.WriteLine("exit Main .."); Console.Read(); }
上面的代码执行后是这个样子的,如下图:
仔细看代码SimonDemo是以动态类型 dynamic来接收的,我们把代码改成SimonDemo simon = new SimonDemo();后执行会怎么样?如下图:
实践后发现,如果需要用KingAop进行横向切面则必须在实例化被切面的类时用动态类型dynamic接收。
整体而言,这个框架还是挺简单的