收藏 分享(赏)

C#实现动态代理.doc

上传人:11xg27ws 文档编号:6399684 上传时间:2019-04-11 格式:DOC 页数:16 大小:105KB
下载 相关 举报
C#实现动态代理.doc_第1页
第1页 / 共16页
C#实现动态代理.doc_第2页
第2页 / 共16页
C#实现动态代理.doc_第3页
第3页 / 共16页
C#实现动态代理.doc_第4页
第4页 / 共16页
C#实现动态代理.doc_第5页
第5页 / 共16页
点击查看更多>>
资源描述

1、转基于 Dynamic Proxy 技术的方法拦截器开发 来自代理技术- 代码变得更简洁在面向对象编程中,会用到大量的类,并且会多次调用类中的方法。有时可能需要对这些方法的调用进行一些控制。如在权限管理中,一些用户没有执行某些方法的权限。又如在日志系统中,在某个方法执行完后,将其执行的结果记录在日志中。处理这些需求的一般做法是在调用这些方法的地方加上适当的代码。如以下 C#代码如示:public class Class1public void MyMethod().static void Main()Class1 c1 = new Class1();if(permit()c1.MyMethod

2、();logger();在以上代码中,permit()是一个得到 MyMethod 方法执行权限的函数,如果 MyMethod 方法可以被执行,那么 permit()返回 true,否则,返回 false。logger() 是记录日志的函数。我们可以看出,在这段程序中存在一个问题,就是它的主要功能是执行 MyMethod 方法,至于权限控制以及日志功能只是它的次要功能(这里说它们是次要功能,并不是说它们不重要,而是说没有这些功能并不影响程序的核心功能的执行)。而将这些次要功能和程序的主要业务逻辑混在一起,如果程序所涉及的类比较多的话,这些次要功能的代码将和业务逻辑代码紧密地结合在一起,这样在修

3、改某一部分时(比如换一个写日志的函数),必须要修改大量的代码。而且程序员在考虑业务逻辑的同时,还要关注这些次要功能,从而无法将精力集中在业务逻辑上。根据以上在软件开发中存在的不足,人们提出了代理(Proxy)技术用以解决上述的问题。代理技术的基本原理是在待调用类和调用者之间加了一个代理类(Proxy Class),这个代理类有两个作用。第一个作用是执行被代理类的方法。第二个作用是在代理类中可以加入控制这个方法的代码,从而使调用者不必关心和自己的业务无关的事情。现将上例用代理技术重新实现,代码如下: 代码 public class Class1public virtual void MyMeth

4、od()/public class ProxyClass1 : Class1public override void MyMethod()if (permit()base.MyMethod();logger();static class Program/static void Main()Class1 pc1 = new ProxyClass1();pc1.MyMethod();/从以上代码可以看出,所有的次要功能代码(在这里指权限和日志)都被放到了代理类中,而在主程序中只有和业务逻辑相关的代码(在这里指 MyMethod 方法)。从而可以达到将次要功能和主要功能分开的目的。但使用代理技术也有

5、其不足之处。从以上代码可以看出,如果在 Class1 中加入一个方法,那么就得在 ProxyClass1 中加入一个方法来 override。如果有非常多的类,那么工作量是相当巨大的,并且有很多重复代码。于是一种经过改良的代理技术出现了,这就是下面要介绍的动态代理(Dynamic Proxy)技术。它的基本原理和代理技术类似,只是生成代理类是完全自动的,而且可以对方法进行匹配控制(如对所有以 My 开头的方法进行控制 )。动态代理(Dynamic Proxy)更快捷的代理技术动态代理(Dynamic Proxy)从它的名字就可以看出这项技术的核心就是“动态” 。它可以根据被代理类自动生成代理类

6、。如果要向 Class1 中增加或删除方法时,可以完全不用考虑代理类的事情,因为这些代理类都是自动生成的,调用者根本就感觉不到。Dynamic Proxy 技术的基本原理是通过扫描被代理类的所有 public 方法,并且自动生成一个从被代理类继承的类,然后在这个生成的类中 override 这些 public 方法。说到这,需要解释一下自动生成代理类。这里说的自动生成,并不是象我们平常所说的生成源代码,而是直接使用中间语言(Intermedial Language)直接在内存中生成。这样在速度上和源码编译而成的中间语言相近。我们可以利用Reflection Emit API 来直接生成中间语言

7、。下面就详细介绍一下自动生成动态代理类的过程。生成中间语言的先期工作初始化为了生成中间语言,需要一个 ModuleBuilder 对象。Module 在 Assembly 中相当于资源(如Class, Interface,Enum 等)的集合,一个 Assembly 中可以有多个 Module。下面是实现初始化Module 的代码:代码 private ModuleBuilder m_Module;private AssemblyBuilder m_Assembly;private void InitModule()AppDomain domain = AppDomain.CurrentDom

8、ain;AssemblyName asmName = new AssemblyName(“DynamicModule“);m_Assembly = domain.DefineDynamicAssembly(asmName, AssemblyBuilderAccess.RunAndSave);m_Module = m_Assembly.DefineDynamicModule(“Module“, “DynamicProxy.dll“);在这个初始化过程中,首先在当前域中建立一个动态的装配集(Dynamic Assembly),然后用它建立一个动态模块(Dynamic Module)。“Module

9、” 是这个动态模块的名字,而后面的“DynamicProxy.dll”是为了在生成代理类后将其保存到硬盘上,以便观察生成的结果。得到当前域有很多方法,也可以将这个函数的第一条语句换成 AppDomain domain = System.Threading.Thread.GetDomain();。 在编写以上代码之前,需要引入两个 namespace。using System.Reflection;using System.Reflection.Emit;在 Dynamic Module 中定义一个代理类现在我们开始在 Dynamic Module 中定义一个代理类。在 Reflection E

10、mit API 中将Class、 Interface 等称为 Type,通过 TypeAttributes 指定具体的行为。下面是定义代理类的具体实现代码:代码 private TypeBuilder m_TypeBuilder;private Type m_Type;private void GenerateType()m_TypeBuilder = m_Module.DefineType(m_Type.Name + “_“ + m_Type.GetHashCode().ToString(),TypeAttributes.Class | TypeAttributes.Public | Typ

11、eAttributes.Sealed, m_Type);从以上代码可以看出,代理类是通过 Dynamic Module 中的 DefineType 方法建立的。这个代理类的名字是被代理类的名称后面接“-”,再加上被代理类的 Hash Code。m_Type 变量保存的是被代理类的 Type,它是通过 Create(这个方法在以后介绍)方法传入。这个方法的第二个参数是说明使用DefineType 建立的类型种类。在这里表明建立一个公共(Public)的、不可被继承的(Sealed)类(Class )。DefineType 的默认动作是建立一个类,因此 TypeAttributes.Class 可

12、以省略。最后一个参数代理所定义的代理类是从 m_Type 所指向的类继承的。为每一个 public 方法生成一个 Nested Class到这一步,我们已经进入 Dynamic Proxy 的最核心的部分。在看实现代码之前,先介绍一下Dynamic Proxy 所涉及的技术细节。在前面已经说过,Dynamic Proxy 是通过继承技术在子类中干预父类方法的执行。但是这个子类,也就是代理类,是自动生成的,调用者根本感觉不到它的存在,如果按以上所说的技术,用户是无法在一个自己无法干预的类中写代码的。这样就需要我们在生成代理类时提供一个外部可访问的机制。在代理类中某个 override 方法执行时

13、,不是直接调用被代理类的方法,而是使用这个机制来引发一个用户可干预的动作。更具体地说,就是将被代理类的方法通过这个机制交给调用者来执行,而不是由代理类自己执行。如果要实现这种机制,就需要使用一个类MulticastDelegate。MulticastDelegate 的作用相当于 C/C+中函数指针。但是需要注意的是 MulticastDelegate 在C#源代码中是不可被继承的,它只能在 IL 中被继承。使用 IL 生成的代码被译成 C#源码如下如示:public sealed class Method_delegate : MulticastDelegatepublic Method_d

14、elegate(object local, IntPtr i);public override void Invoke(string str);这段代码是声明一个从 MulticastDelegate 继承的类,这个子类中保存了相应的方法指针。其中这个类的构造函数有两个参数,一个是这个子类的对象引用(object local),另外一个是方法的指针(IntPtr i)。另外 Invoke 方法的参数是根据被代理类中相应方法的参数而确定的,在这个例子中,只有一个string 类型的参数。需要注意的是这个类无法用 C#编译,它只能用 IL 写。我们会为被代理类中的每一个 public 方法都生成这

15、么一个类,然后将相对应的方法的指针保存在这个类中,最后将这个类作为参数传出去,供用户调用。下面是自动生成这些类的具体实现:代码 private TypeBuilder m_NestedTypeBuilders;private ConstructorBuilder m_NestedTypeConstructors;private void GenerateDelegateClass()MethodInfo methodInfos = m_Type.GetMethods();/得到被代理类的所有 public 方法信息/根据方法的个数初始化 Nested Type 数组,以后将保存并使用到这些值m

16、_NestedTypeBuilders = new TypeBuildermethodInfos.Length;m_NestedTypeConstructors = new ConstructorBuildermethodInfos.Length;/开始为每一个方法建立 Nested Classfor (Int32 i = 0; i m_NestedTypeBuilders.Length; i+)/建立 Nested Classm_NestedTypeBuildersi = m_TypeBuilder.DefineNestedType(“_“ + methodInfosi.Name + “_d

17、elegate“,TypeAttributes.NestedPrivate | TypeAttributes.Sealed, typeof(MulticastDelegate);/为每一个 Nested Class 加一个构造函数(Constructor) m_NestedTypeConstructorsi = m_NestedTypeBuildersi.DefineConstructor(MethodAttributes.Public,CallingConventions.Standard, new Type typeof(Object), typeof(IntPtr) );m_Nested

18、TypeConstructorsi.SetImplementationFlags(MethodImplAttributes.Runtime |MethodImplAttributes.Managed);Type argsType = GetParameterTypes(methodInfosi);/在这个 Nested Class 中加入一个在运行时(runtime)管理的 Invoke 方法MethodBuilder mb = m_NestedTypeBuildersi.DefineMethod(“Invoke“, MethodAttributes.Public,CallingConvent

19、ions.Standard, methodInfosi.ReturnType, argsType);mb.SetImplementationFlags(MethodImplAttributes.Runtime | MethodImplAttributes.Managed);/得到一个方法所有参数的 Type 数组,这个方法在以后会被多次调用private Type GetParameterTypes(MethodInfo methodInfo)ParameterInfo args = methodInfo.GetParameters();Type argsType = new Typeargs

20、.Length;for (Int32 j = 0; j args.Length; j+) argsTypej = argsj.ParameterType; return argsType;以上代码有几点需要注意。1、生成嵌套类(Nested Class),要使用 DefineNestedType,而不能用 DefineType。在使用Type Attributes 时要用 NestedPrivate 或 NestedPublic,不能用 NotPublic 或 Public。2、在这里定义的构造函数(Constructor)和传统意义上的构造函数不一样。因为这个构造函数只有函数头,而没有函数体

21、。这是为什么呢?答案可以从它的下一条语句得到。在这条语句中用了SetImplementationFlags 方法将这个构造函数设成了 Runtime 和 Managed。也就是说这个构造函数是在运行时管理的,而不是由 cil 管理的。即它的函数体是在运行过程中生成的,而不是事先写好的。3、Invoke 方法的定义和构造函数的定义类似,也没有函数体。它也是在运行时管理的。为每一个 Nested Class 声明一个变量为了保存相应的函数指针,我们来为每一个 Nested Class 定义一个变量。这些变量在稍后将在代理类的构造函数中进行初始化。下面是定义变量的实现代码:代码 private Fi

22、eldBuilder m_MultiCastDelegates;private void GenerateFields()/ 声明_Interceptor 变量m_Interceptor = m_TypeBuilder.DefineField(“_Interceptor“, typeof(Interceptor), FieldAttributes.Private);/ 开始为每一个 Nested Class 声明一个变量MethodInfo methodInfos = m_Type.GetMethods();m_MultiCastDelegates = new FieldBuildermeth

23、odInfos.Length;for (Int32 i = 0; i methodInfos.Length; i+)m_MultiCastDelegatesi = m_TypeBuilder.DefineField(methodInfosi.Name + “_field“, m_NestedTypeBuildersi, FieldAttributes.Private);这个方法的第一条语句是声明一个 Interceptor 类型的变量,Interceptor 是用户定义的一个类,负责截获方法的执行。_Interceptor 是通过代理类的参数来传入的,这个将在以后介绍。声明一个变量用TypeB

24、uilder 中的 DefineField 方法,这里声明的是一个 private 类型的变量。变量类型是m_NestedTypeBuildersi中所指的类型。回调(Callback)方法的生成以前曾讲过,代理类中 override 方法是在方法体内使用“base”调用父类的同名方法。但是这样做有一些问题,当我们将 override 方法的指针存入 Nested Class 变量,并且在 Interceptor 中的 Call(这个方法将在以后介绍)方法中执行这个 override 方法,会产生一个嵌套调用。因为 Call 方法是在代理类中的 override 方法中调用的。因此我们需要加入

25、另外一个方法(称为回调方法)来调用父类的方法,并且将这个回调方法的指针加入到 Nested Class 变量中。下面是回调函数的实现代码:代码 private MethodBuilder m_CallBackMethods;private void GenerateCallBackMethods()MethodInfo methodInfos = m_Type.GetMethods();m_CallBackMethods = new MethodBuildermethodInfos.Length;for (Int32 i = 0; i methodInfos.Length; i+)Type a

26、rgTypes = GetParameterTypes(methodInfosi); / 得到当前方法所有参数的 Typem_CallBackMethodsi = m_TypeBuilder.DefineMethod(“callback_“ + methodInfosi.Name, MethodAttributes.Private, CallingConventions.Standard, methodInfosi.ReturnType,argTypes);/定义回调方法/得到 IL 的产生器ILGenerator ilGenerator = m_CallBackMethodsi.GetILG

27、enerator();ilGenerator.Emit(OpCodes.Ldarg_0); / 将代理类的引用压入 evaluation 栈for (Int32 j = 0; j argTypes.Length; j+)ilGenerator.Emit(OpCodes.Ldarg, j + 1); /将回调函数的每一个参数压入 evaluation栈ilGenerator.Emit(OpCodes.Call, methodInfosi);/调用父类的方法ilGenerator.Emit(OpCodes.Ret);/返回在上面的方法中涉及到 C#的一项重要技术,那就是直接在 C#源代码中写 IL

28、,并且这些 IL 是在内存中直接通过.net framework 二次编译成本地代码。在这个方法中首先用 DefineMethod 定义一个回调方法。然后通过 GetILGenerator 方法得到一个 IL 产生器。在产生器中,写 IL 主要是通过 Emit 方法实现的。IL 指令可以通过 OpCodes 类得到。有一个概念在这里不得不提,那就是 evaluation 栈。这个栈在向方法中写入 IL 时自动建立,它的主要作用是在调用方法、建立对象等需要传递参数时,需先将这些要传的参数值按顺序压入栈中,然后再执行相关的操作。在这个方法中,调用父类方法时,先将方法的参数压栈,再调用方法。在调用时

29、,方法依次将 evaluation 栈中的值依次出栈。在每一个方法的最后的一条 IL 语句必须是 OpCodes.Ret,而不管方法是否需要返回值,如果 evaluation 栈到最后还剩一个值,那么这条指令将这个值出栈返回。当然,如果方法返回的是 void,将抛出例外。或者方法有返回值,而evaluation 为空,那么同样会抛出例外。覆盖(Override) 方法的生成Override 函数是面向用户的接口。它负责向用户提供调用回调方法的机制(通过 Interceptor 的Call 方法)。实现代码如下:代码 private void GenerateOverrideMethods()M

30、ethodInfo methodInfos = m_Type.GetMethods();for (Int32 i = 0; i methodInfos.Length; i+)Type argTypes = GetParameterTypes(methodInfosi);MethodBuilder mb = m_TypeBuilder.DefineMethod(methodInfosi.Name,MethodAttributes.Public | MethodAttributes.Virtual, CallingConventions.Standard,methodInfosi.ReturnTy

31、pe, argTypes);/定义 override 方法ILGenerator ilGenerator = mb.GetILGenerator();/将 m_Interceptor 变量压入栈ilGenerator.Emit(OpCodes.Ldarg_0);ilGenerator.Emit(OpCodes.Ldfld, m_Interceptor);/将 Call 的第一个参数压栈ilGenerator.Emit(OpCodes.Ldstr, methodInfosi.Name);/将 Call 的第二个参数压栈ilGenerator.Emit(OpCodes.Ldarg_0);ilGen

32、erator.Emit(OpCodes.Ldfld, m_MultiCastDelegatesi);/将 Call 的第三个参数压栈LocalBuilder local = ilGenerator.DeclareLocal(typeof(Object);ilGenerator.Emit(OpCodes.Ldc_I4, argTypes.Length);ilGenerator.Emit(OpCodes.Newarr, typeof(Object);ilGenerator.Emit(OpCodes.Stloc, local);ilGenerator.Emit(OpCodes.Ldloc, loca

33、l);for (Int32 j = 0; j argTypes.Length; j+)ilGenerator.Emit(OpCodes.Ldc_I4, j);ilGenerator.Emit(OpCodes.Ldarg, j + 1);ilGenerator.Emit(OpCodes.Box, argTypesj);ilGenerator.Emit(OpCodes.Stelem_Ref);ilGenerator.Emit(OpCodes.Ldloc, local);/调用 Call 方法ilGenerator.Emit(OpCodes.Call, typeof(Interceptor).Get

34、Method(“Call“, newType typeof(String), typeof(MulticastDelegate), typeof(Object) );if (methodInfosi.ReturnType.Equals(typeof(void)ilGenerator.Emit(OpCodes.Pop);/如果 override 方法返回 void, 将 Call 返回的 null 出栈else/将返回值是值类型(value type)时拆箱(Unbox)ilGenerator.Emit(OpCodes.Unbox_Any, methodInfosi.ReturnType);il

35、Generator.Emit(OpCodes.Ret);在上面的代码中出现了一个 OpCodes.Newarr 指令,功能是建立一个数组。这个数组中保存的是override 方法传进来的参数值。另外还需要提到一点,当这个 override 方法返回 void 时,Call 返回的是 null,因此必须将这个 null 从 evaluation 栈弹出来才能执行正确。如果 override 的返回值是一个值类型(如 int、float 等),必须调用 OpCodes.Unbox_Any 指令,否则不能正确地返回值。生成代理类的构造函数到这里,这个代理类已经基本完成了。但还缺一个最重要的部分构造函

36、数。这个构造函数主要有两个功能。1、调用父类相应的构造函数。2、初始化相关的变量。实现代码如下:代码 private void GenerateConstructor()m_ConstructorBuilder = m_TypeBuilder.DefineConstructor(MethodAttributes.Public, CallingConventions.Standard, new Type typeof(Interceptor) );ILGenerator ilGenerator = m_ConstructorBuilder.GetILGenerator();/调用父类构造函数(假

37、设父类只有无参数的构造函数)ilGenerator.Emit(OpCodes.Ldarg_0);ilGenerator.Emit(OpCodes.Call, m_Type.GetConstructor(new Type );/ 初始化_Interceptor 变量ilGenerator.Emit(OpCodes.Ldarg_0);ilGenerator.Emit(OpCodes.Ldarg_1);ilGenerator.Emit(OpCodes.Stfld, m_Interceptor);/ 初始化 Nested Class 变量for (Int32 i = 0; i m_MultiCastD

38、elegates.Length; i+)ilGenerator.Emit(OpCodes.Ldarg_0);ilGenerator.Emit(OpCodes.Ldarg_0);ilGenerator.Emit(OpCodes.Ldftn, m_CallBackMethodsi);ilGenerator.Emit(OpCodes.Newobj, m_NestedTypeConstructorsi);ilGenerator.Emit(OpCodes.Stfld, m_MultiCastDelegatesi);ilGenerator.Emit(OpCodes.Ret);这个构造函数有一个 Inter

39、ceptor 类型的参数。将初始化 Nested Class 变量的指令集转换为 C#源码为:m_MultiCastDelegatesi = new Method_Delegate(this, m_CallBackMethodsi),Method_Delegate 为相应的 Nested Class 类名。在前面许多地方都提到了 Interceptor 类,这个类是代理类的使用者自己定义的,然后通过参数传入代理类。类中只有一个 Call 方法。代码如下:public Object Call(String methodName, MulticastDelegate methodDelegate,

40、 params Object args)return methodDelegate.Method.Invoke(methodDelegate.Target, args);这个方法有三个参数,第一个参数是 override 方法的名字,第二个参数就是代理类中的相应的Nested Class 变量,第三个参数是相应 override 方法的参数值。通过这个方法,调用者可以根据methodName,args 等信息对 override 进行控制。假设有一个名字 MyMethod 的 override 方法,如果我们想让这个方法执行完后写一条日志,那么这个 Call 函数可以这么写:代码 public

41、 Object Call(String methodName, MulticastDelegate methodDelegate, params Object args)Object obj = methodDelegate.Method.Invoke(methodDelegate.Target, args);if (methodName.Equals(“MyMethod“)logger();return obj;这样所有调用 MyMethod 的语句都会在这个方法执行完后执行 logger()函数写日志。Wrap 函数的建立在前面已经建立了实现 Dynamic Proxy 所需的所有方法,最

42、后要做的工作就是将这些方法组合起来。这些工作将在 Wrap 方法中完成:代码 public Object Wrap(Type type)Type newType = null;trym_Type = type;GenerateType();GenerateDelegateClass();GenerateFields();GenerateCallBackMethods();GenerateOverrideMethods();GenerateConstructor();newType = m_TypeBuilder.CreateType(); /建立代理类的 Type/建立 Nested Clas

43、s 的 Typeforeach (TypeBuilder tb in m_NestedTypeBuilders)tb.CreateType();m_Assembly.Save(“DynamicProxy.dll“); /保存这个代理类为 DynamicProxy.dllcatch (Exception err)throw err;/建立代理类实例return Activator.CreateInstance(newType, new Interceptor();在这个方法中,有一个地方需要注意,在建立一个 Nested Class 之前,应先建立包含这个 Nested Class 的类,然后再

44、建立 Nested Class。在建完代理类后,将其保存在 DynamicProxy.dll 中(如果你感兴趣,可以用 Microsoft 的 ildasm.exe 查看这个 dll 的 IL。)。最后建立了代理类的实例,将Interceptor 的一个实例通过参数传入到代理类的构造函数中。如何应用动态代理技术至此所有的工作都完成了。我们可以将以上代码放入一个叫 DynamicProxyBuilder 的类中。以下代码是如何使用 DynamicProxyBuilder 的一个例子:DynamicProxyBuilder dynamicProxyBuilder = new DynamicProx

45、yBuilder();Class1 class1 = (Class1)dynamicProxyBuilder.Wrap(typeof(Class1);class1.MyMethod(); 以上代码可以为 Class1 生成一个代理类,如果用户想控制这个方法,可以在 Call 方法中加入适当的代码即可。在使用 DynamicProxyBuilder 时需要注意两点:1、被代理类的 public 方法必须都是 virtual 的,否则无法继承。2、在建立一个类时必须用 Wrap,而不能直接用 new 关键字。总结Dynamic Proxy 技术也是 AOP(Aspect Oriented Prog

46、ramming)技术的核心。通过动态代理实现的 AOP,一般可分为两个部分。第一部分是动态代理的实现,在这部分不同的语言在实现上有很大的不同。由于 C#没有提供象 java 那样的动态代理机制,因此这些工作必须由我们自己来做,以上所述便是用 C#实现动态代理的全部过程。第二部分就是利用这个动态代理机制来控制方法的执行。由上述可知,在这个方法拦截器中有一个用于改变方法调用轨迹的类 Interceptor,当调用被代理类方法时,先调用这个类中的 Call 方法,然后在 Call 方法中加入适当代码来决定是否执行这个被代理类的方法。我们可以更进一步地去想,如果在 Call 方法中加入一些和 AOP

47、相关的代码,例如在满足一定条件下,在方法执行之前或执行之后插入一些代码,或者干脆不让这个方法执行。这样就成为一个真正的 AOP framework了。AOP 是动态代理的最具代表性的应用。它在程序设计中的应用十分广泛。在一般的系统中,可分为两个部分,核心功能和系统功能。所谓核心功能就是和这个系统相关的业务功能,如在 mail 服务器中的核心功能是接收和发送电子邮件。系统功能则可以看成是系统的可选功能,如日志、安全等。如果没有了这些功能,mail 服务器仍可以照常工作,只是不太安全了,并且无法查找以往的记录。实现这些系统功能,一般的作法是将系统功能的代码和核心功能的代码混在一起。这样做不仅加大了

48、系统设计和实现的难度,而且使设计系统核心功能的程序必须要考虑这些系统的功能,分散了他们的注意力。然而,利用AOP 却可解决以上问题,从而达到分离核心功能和系统功能的目的。除了 AOP,动态代理还有许多其它的用途。比如我们要开发一个远程服务的程序。在客户端要执行服务端的一些方法。一般的作法是利用.net remoting 或直接用 socket 进行通讯,告诉服务器要调用的方法,然后服务器调用方法后通过.net remoting 或 socket 将执行结果返回。这样做从表面上看没什么问题。但是对于某些方法的调用,并不要求结果的实时变化,也就是说当服务器上的数据变化了,并不要求通过这个方法得到的

49、数据马上变化,可以有一段时间的延迟。如果是这样的话,那么每次都让服务器重新执行这个方法好象有点得不偿失。由此我们自然想到了 Cache(缓存)。当要被缓存的方法在第一次调用后,将其结果存入 Cache。当以后再调用这个方法时,可以直接从 Cache 中取结果,而无需每次都执行这个方法。但这样还有一个问题,如果我们无法修改这个服务器的代码,那么如何加入有关 Cache的代码呢?即使能修改代码,那么我们是否能当不需要这个 Cache 时很容易地将其关闭呢?如果这个服务器使用了动态代理或者直接使用了利用动态代理技术实现的 AOP,这么这些问题简直就是小菜一碟。即使你不了解服务器的源代码甚至是没有源代码,你仍可以利用方法拦截来实现这个 C

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 企业管理 > 代理连锁

本站链接:文库   一言   我酷   合作


客服QQ:2549714901微博号:道客多多官方知乎号:道客多多

经营许可证编号: 粤ICP备2021046453号世界地图

道客多多©版权所有2020-2025营业执照举报