ImageVerifierCode 换一换
格式:DOCX , 页数:11 ,大小:62.34KB ,
资源ID:7582332      下载积分:3 金币
快捷下载
登录下载
邮箱/手机:
温馨提示:
快捷下载时,用户名和密码都是您填写的邮箱或者手机号,方便查询和重复下载(系统自动生成)。 如填写123,账号就是123,密码也是123。
特别说明:
请自助下载,系统不会自动发送文件的哦; 如果您已付费,想二次下载,请登录后访问:我的下载记录
支付方式: 支付宝    微信支付   
验证码:   换一换

加入VIP,免费下载
 

温馨提示:由于个人手机设置不同,如果发现不能下载,请复制以下地址【https://www.bdocx.com/down/7582332.html】到电脑端继续下载(重复下载不扣费)。

已注册用户请登录:
账号:
密码:
验证码:   换一换
  忘记密码?
三方登录: 微信登录   QQ登录  

下载须知

1: 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。
2: 试题试卷类文档,如果标题没有明确说明有答案则都视为没有答案,请知晓。
3: 文件的所有权益归上传用户所有。
4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
5. 本站仅提供交流平台,并不能对任何下载内容负责。
6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

版权提示 | 免责声明

本文(动态代理之AOP实现.docx)为本站会员(b****6)主动上传,冰豆网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。 若此文所含内容侵犯了您的版权或隐私,请立即通知冰豆网(发送邮件至service@bdocx.com或直接QQ联系客服),我们立即给予删除!

动态代理之AOP实现.docx

1、动态代理之AOP实现动态代理方式实现AOP 摘要:面向对象的思想强调一切皆是对象,在面向对象的程序中我们使用真实概念的模型思考问题,使得整个软件系统开发可以像搭建房屋一样有条不紊。然而面向对象也并非完美无缺的,它更注重于对象层次结构方面的东西,对于如何更好的管理对象行为内部结构,还存在着些许不足。那么我们如何使这个问题的得到更完美的解决呢?答案就是AOP。 主要内容: AOP简述 利用动态代理实现AOP 总结 一、AOP简述 AOP的概念早在上个世纪九十年代初就已经出现了,当时的研究人员通过对面向对象思想局限性的分析研究出了一种新的编程思想来帮助开发者减少代码重复提高开发效率,那就是AOP,A

2、spect-Oriented Programming。AOP是OOP的补充,是GOF的延续。我们知道设计模式是对于面向对象设计中经验的总结,它孜孜不断追求的就是调用者与被调用者之间的解耦。有了设计模式我们可以更有效的利用面向对象的特性,使得整个软件设计更加灵活、优雅。但是设计模式是基于面向对象的思想而形成的,更多的时候关注的是对象层次的东西,在解决对象行为内部问题方面却有些不足。AOP的出现恰恰就是对面向对象思想做出了完美的补充。 上图显示了软件的纵向和横向结构,从纵向结构来看就是我们软件系统的各个模块,它主要负责处理我们的核心业务(例如商品订购、购物车查看);而从横向结构来看,我们几乎每个系

3、统又包含一些公共模块(例如权限、日志模块等)。这些公共模块分布于我们各个核心业务之中(例如订购和查看商品明细的过程都需要检查用户权限、记录系统日志等)。这样一来不仅在开发过程中要处处关注公共模块的处理而且开发后维护起来也是十分麻烦。而有了AOP之后将应用程序中的商业逻辑同对其提供支持的通用服务进行分离,使得开发人员可以更多的关注核心业务开发。 二、利用动态实现AOP 上面我们说了一些关于AOP所要解决的问题以及这样做的好处,下面我们主要看一下如何实现AOP。 AOP的实现一般分为:动态代理(DynamicProxy)和静态织入(StaticWeave)两种方式。这里我们主要说的是如何利用Emi

4、t来自己实现动态代理方式的AOP(关于Emit的知识大家可以看一下我的另一篇博客反射发出-Emit),以此来帮助大家更深入的理解AOP。 在开始动态代理之前假设我们有这样一个类,它是负责处理我们的业务逻辑的。 先看对应接口代码 using System;using System.Collections.Generic;using System.Linq;using System.Text;namespace DanymicProxy interface IBusinessLogic void ShowMessage(string msg); int Calculate(); 相应的类代码 us

5、ing System;using System.Collections.Generic;using System.Linq;using System.Text;namespace DanymicProxy public class MyBusinessLogic:IBusinessLogic public virtual void ShowMessage(string msg) Console.WriteLine(msg); public virtual int Calculate() int sum=0; for (int i = 1; i = 100; +i) sum += + i; Co

6、nsole.WriteLine(sum); return sum; 现在我们需要给所有的核心业务添加日志记录功能,此时大概会有下面几种选择: 1.在ShowMessage和Calculate内部都添加上记录日志的代码 。代码 using System;using System.Collections.Generic;using System.Linq;using System.Text;namespace DanymicProxy public class MyBusinessLogic:IBusinessLogic public virtual void ShowMessage(string

7、 msg) Console.WriteLine(DateTime.Now.ToString() + :DanymicProxy.MyBusinessLogic ShowMessage is called!); Console.WriteLine(msg); Console.WriteLine(DateTime.Now.ToString() + :DanymicProxy.MyBusinessLogic ShowMessage has finished!); public virtual int Calculate() Console.WriteLine(DateTime.Now.ToStrin

8、g() + :DanymicProxy.Calculate ShowMessage is called!); int sum=0; for (int i = 1; i = 100; +i) sum += + i; Console.WriteLine(sum); Console.WriteLine(DateTime.Now.ToString() + :DanymicProxy.Calculate ShowMessage has finished!); return sum; 2.重新写一个类继承于MyBusinessLogic并对其中的方法重写。代码 using System;using Sys

9、tem.Collections.Generic;using System.Linq;using System.Text;namespace DanymicProxy class MyBusinessLogicDecoration:MyBusinessLogic public override void ShowMessage(string msg) Console.WriteLine(DateTime.Now.ToString() + :DanymicProxy.MyBusinessLogic ShowMessage is called!); base.ShowMessage(msg); Co

10、nsole.WriteLine(DateTime.Now.ToString() + :DanymicProxy.MyBusinessLogic ShowMessage has finished!); public override int Calculate() Console.WriteLine(DateTime.Now.ToString() + :DanymicProxy.Calculate ShowMessage is called!); int t=base.Calculate(); Console.WriteLine(DateTime.Now.ToString() + :Danymi

11、cProxy.Calculate ShowMessage has finished!); return t; 3.写一个静态代理类。 首先看一下代理中用到的拦截器接口代码 using System;using System.Collections.Generic;using System.Linq;using System.Text;namespace DanymicProxy public interface IInterceptor object Invoke(object obj,string methodName,object parameters); 然后编写一个操作日志的拦截器代码

12、 using System;using System.Collections.Generic;using System.Linq;using System.Text;namespace DanymicProxy public class LogInterceptor:IInterceptor public object Invoke(object obj, string methodName, object parameters) Console.WriteLine(DateTime.Now.ToString()+:+obj.ToString()+s +methodName+ is calle

13、d!); object rst= obj.GetType().GetMethod(methodName).Invoke(obj,parameters); Console.WriteLine(DateTime.Now.ToString() + : + obj.ToString() + s + methodName + has finished!); return rst; 再看静态代理类代码 using System;using System.Collections.Generic;using System.Linq;using System.Text;using DanymicProxy;na

14、mespace DanymicProxy class MyBusinessLogicProxy private IInterceptor _interceptor = null; public MyBusinessLogicProxy(IInterceptor interceptor) _interceptor = interceptor; public virtual void ShowMessage(string msg) _interceptor.Invoke(new MyBusinessLogic(), ShowMessage, new object msg ); public vir

15、tual int Calculate() return Convert.ToInt32(_interceptor.Invoke(new MyBusinessLogic(), Calculate, null); 接着我们可以使用下面的代码做测试代码 using System;using System.Collections.Generic;using System.Linq;using System.Text;namespace DanymicProxy class Program static void Main(string args) (new MyBusinessLogicProxy(n

16、ew LogInterceptor().ShowMessage(Hello World!); (new MyBusinessLogicProxy(new LogInterceptor().Calculate(); 4.使用动态代理相对于前两种方法,第三种方法应该算是比较好的方法了,可是做起来比较麻烦。不仅必须给每个业务类都重新写一个包含日志处理的代理类,而且如果我有其他类似日志处理的模块(例如权限模块)需要添加还要再写包含其他功能的代理类。这样做起来不仅工作量大,而且再维护起来也十分麻烦。怎么办?方法就是使用动态代理。 我们下面要实现的动态代理,其运行机制和上面说的静态代理可以说是完全相同的(

17、事实上我们编写Emit的时候就是仿照静态代理类来写的),只不过重复写代理类的工作交给程序来做了而已。 具体过程:首先根据泛型类型创建名字为泛型+Proxy的类;在类中声明一个IInterceptor型的私有变量_interceptor赋值为null;接着创建构造函数,其参数为IInterceptor类型;然后我们遍历泛型中的方法,创建名称、返回类型、参数均与泛型方法一致的方法,然后在方法中使用interceptor的Invoke方法调用对应的方法(参数分别为泛型对象、方法名和参数);最后实例化此类,并将其返回。 代码 using System;using System.Collections.

18、Generic;using System.Linq;using System.Text;using System.Reflection;using System.Reflection.Emit;namespace DanymicProxy public class Proxy where T:class public static T CreateProxy(IInterceptor interceptor) /构建程序集 AssemblyName aName = new AssemblyName(Cmj.DotNet); AppDomain aDomain = AppDomain.Curre

19、ntDomain;/应用程序域,这里设为当前域 AssemblyBuilder aBuidler = aDomain.DefineDynamicAssembly(aName, AssemblyBuilderAccess.RunAndSave); /定义模块 ModuleBuilder mBuidler = aBuidler.DefineDynamicModule(MyModule,Cmj.DotNet.dll); /创建类型(其实就是一个类) StringBuilder sbClassName = new StringBuilder(Cmj.DotNet.); sbClassName.Appe

20、nd(typeof(T).Name); sbClassName.Append(Proxy); TypeBuilder tBuidler = mBuidler.DefineType(sbClassName.ToString(), TypeAttributes.Public | TypeAttributes.Class,typeof(T);/继承于T /-实现类-/ /定义私有字段 FieldBuilder fbInterceptor = tBuidler.DefineField(_interceptor, typeof(IInterceptor), FieldAttributes.Private

21、); /为私有变量赋值 fbInterceptor.SetConstant(null); /定义构造函数 ConstructorBuilder ctstBuilder = tBuidler.DefineConstructor(MethodAttributes.Public, CallingConventions.Standard, new Type typeof(IInterceptor); ILGenerator ctstGenerator = ctstBuilder.GetILGenerator(); ctstGenerator.Emit(OpCodes.Ldarg_0); ctstGen

22、erator.Emit(OpCodes.Ldarg_1); ctstGenerator.Emit(OpCodes.Stfld, fbInterceptor);/给字段赋值 ctstGenerator.Emit(OpCodes.Ret); /定义方法 MethodInfo methods = typeof(T).GetMethods(BindingFlags.Instance | BindingFlags.Public); Type retType=null; Type paramsType=null; ParameterInfo parameters=null; MethodBuilder m

23、tdBuidler=null; ILGenerator mtdGenerator = null; foreach (MethodInfo method in methods) if (method.Name != ToString & method.Name != Equals & method.Name != GetHashCode & method.Name != GetType) /获得返回值类型 retType = method.ReturnType; /获得参数类型 parameters = method.GetParameters(); paramsType = new Typep

24、arameters.Length; for (int i = 0; i parameters.Length; +i) paramsTypei = parametersi.ParameterType; /实现方法体 mtdBuidler = tBuidler.DefineMethod(method.Name, MethodAttributes.Public|MethodAttributes.Virtual, CallingConventions.Standard, retType, paramsType); mtdGenerator = mtdBuidler.GetILGenerator();

25、mtdGenerator.Emit(OpCodes.Ldarg_0); mtdGenerator.Emit(OpCodes.Ldfld, fbInterceptor); mtdGenerator.Emit(OpCodes.Newobj, typeof(T).GetConstructor(new Type0); mtdGenerator.Emit(OpCodes.Ldstr, method.Name); if (paramsType.Length = 0) mtdGenerator.Emit(OpCodes.Ldnull); else LocalBuilder paras = mtdGenera

26、tor.DeclareLocal(typeof(object); mtdGenerator.Emit(OpCodes.Ldc_I4, paramsType.Length); mtdGenerator.Emit(OpCodes.Newarr, typeof(object); mtdGenerator.Emit(OpCodes.Stloc, paras); for (var j = 0; j paramsType.Length; j+) mtdGenerator.Emit(OpCodes.Ldloc, paras); mtdGenerator.Emit(OpCodes.Ldc_I4, j); mt

27、dGenerator.Emit(OpCodes.Ldarg, j + 1); mtdGenerator.Emit(OpCodes.Stelem_Ref); mtdGenerator.Emit(OpCodes.Ldloc, paras); mtdGenerator.Emit(OpCodes.Callvirt, typeof(IInterceptor).GetMethod(Invoke); if (retType = typeof(void) mtdGenerator.Emit(OpCodes.Pop); mtdGenerator.Emit(OpCodes.Ret); /创建引用、调用方法 Typ

28、e proxyType = tBuidler.CreateType(); aBuidler.Save(Cmj.DotNet.dll); object proxy = Activator.CreateInstance(proxyType, new object interceptor);/实例化 return proxy as T; 最后我们测试一下 代码 using System;using System.Collections.Generic;using System.Linq;using System.Text;namespace DanymicProxy class Program st

29、atic void Main(string args) Proxy.CreateProxy(new LogInterceptor().ShowMessage(Hello World!); Proxy.CreateProxy(new LogInterceptor().Calculate(); 运行效果 三、总结: 上面简单的介绍了如何用动态代理的方式实现AOP,主要是帮助大家理解动态代理AOP的大致思路。在实际开发中我们可能更多时候会选择一些AOP的工具(例如Castle中的Aspect#、Spring AOP、AspectDNG等),这些内容(包括静态织入方式实现AOP)我们今后有机会再一块学习。

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1