【问题标题】:Why we use Dynamic Proxy为什么我们使用动态代理
【发布时间】:2013-08-21 06:39:19
【问题描述】:

dynamic proxy 类是实现接口列表的类 在运行时指定,以便通过其中一个方法调用 类实例上的接口将被编码和分派 通过统一的接口到另一个对象。它可以用来 为没有的接口列表创建类型安全的代理对象 需要预先生成代理类。动态代理类是 对需要提供类型安全的应用程序或库很有用 对呈现接口的对象的调用的反射调度 蜜蜂

上图是很好的示例,但为什么我们使用动态代理?

有没有一个简单的例子可以在现实世界中使用,以获得更多的感知?

【问题讨论】:

  • IMO 这个问题太宽泛了,你应该把这个问题分成几个独立的问题

标签: c# java proxy


【解决方案1】:

一个常见的用例是Aspect-Oriented Programming,您在其中寻求跨多个组件应用通用功能,而不需要组件本身来实现功能。在这些情况下,您可以使用动态代理来包装所有具有附加行为的目标组件。这样做

几个例子:

  • 诸如 Hibernate 和实体框架之类的 ORM 这样做是为了围绕代码优先设计提供持久性实现。核心领域类是在不了解其持久性的情况下构建的,框架在启动时包装或扩展这些类以处理实际实现。

  • 使用日志或缓存等方面包装接口的所有成员。例如,如果您想记录 ISomeInterface 上的每个方法调用,您可以编写一个动态代理来查找所有接口方法,调用带有方法详细信息的 Log 方法,然后将调用传递给实际实现。

    李>

【讨论】:

    【解决方案2】:

    假设您有两个对象 Car 和 Motorboat,它们分别实现了接口 CanDrive 和 CanFloat。现在,您想要第三个对象来实现这两个接口并重用 Car 和 Motorboat 的逻辑。在 Groovy、Ruby 和 Scala 等语言中,您可以使用 mixin 来解决这个问题。然而,在 Java 中,没有这样的东西。你当然可以使用例如适配器设计模式,但在许多情况下(尤其是在构建框架时)动态代理很有用。考虑使用 cglib 库的示例:

    CanDrive car = new Car();
    CanFloat motorboat = new Motorboat();
    
    net.sf.cglib.proxy.Mixin amphibian = net.sf.cglib.proxy.Mixin.create(new Object[] { car, motorboat });
    
    TestCase.assertEquals("bzzz bzzz bzzz ...", ((CanFloat) amphibian)._float());
    TestCase.assertEquals("pyr pyr pyr pyr ...", ((CanDrive) amphibian).drive());
    

    【讨论】:

      【解决方案3】:

      这个link在代码中描述了动态代理:

      public static class DynamicProxyGenerator  
      {  
          public static T GetInstanceFor<T>()  
          {  
              Type typeOfT = typeof(T);  
              var methodInfos = typeOfT.GetMethods();  
              AssemblyName assName = new AssemblyName("testAssembly");  
              var assBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly(assName, AssemblyBuilderAccess.RunAndSave);  
              var moduleBuilder = assBuilder.DefineDynamicModule("testModule", "test.dll");  
              var typeBuilder = moduleBuilder.DefineType(typeOfT.Name + "Proxy", TypeAttributes.Public);  
      
              typeBuilder.AddInterfaceImplementation(typeOfT);  
              var ctorBuilder = typeBuilder.DefineConstructor(  
                        MethodAttributes.Public,  
                        CallingConventions.Standard,  
                        new Type[] { });  
              var ilGenerator = ctorBuilder.GetILGenerator();  
              ilGenerator.EmitWriteLine("Creating Proxy instance");  
              ilGenerator.Emit(OpCodes.Ret);  
              foreach (var methodInfo in methodInfos)  
              {  
                  var methodBuilder = typeBuilder.DefineMethod(  
                      methodInfo.Name,  
                      MethodAttributes.Public | MethodAttributes.Virtual,  
                      methodInfo.ReturnType,  
                      methodInfo.GetParameters().Select(p => p.GetType()).ToArray()  
                      );  
                  var methodILGen = methodBuilder.GetILGenerator();               
                  if (methodInfo.ReturnType == typeof(void))  
                  {  
                      methodILGen.Emit(OpCodes.Ret);  
                  }  
                  else  
                  {  
                      if (methodInfo.ReturnType.IsValueType || methodInfo.ReturnType.IsEnum)  
                      {  
                          MethodInfo getMethod = typeof(Activator).GetMethod(/span>"CreateInstance",new Type[]{typeof((Type)});                          
                          LocalBuilder lb = methodILGen.DeclareLocal(methodInfo.ReturnType);  
                          methodILGen.Emit(OpCodes.Ldtoken, lb.LocalType);  
                          methodILGen.Emit(OpCodes.Call, typeofype).GetMethod("GetTypeFromHandle"));  ));  
                          methodILGen.Emit(OpCodes.Callvirt, getMethod);  
                          methodILGen.Emit(OpCodes.Unbox_Any, lb.LocalType);  
      
                      }  
                       else  
                      {  
                          methodILGen.Emit(OpCodes.Ldnull);  
                      }  
                      methodILGen.Emit(OpCodes.Ret);  
                  }  
                  typeBuilder.DefineMethodOverride(methodBuilder, methodInfo);  
              }  
      
              Type constructedType = typeBuilder.CreateType();  
              var instance = Activator.CreateInstance(constructedType);  
              return (T)instance;  
          }  
      }  
      

      【讨论】:

      • 这是一个特定的 C# 实现,但不涉及该模式的可能应用
      • 正如我已经说过的:这个链接描述了代码中的动态代理。它让我自己很清楚,所以我认为它可以成为这个问题的一个很好的实用答案。
      【解决方案4】:

      【讨论】:

        猜你喜欢
        • 2010-10-30
        • 2021-09-28
        • 2015-12-08
        • 1970-01-01
        • 2014-09-15
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-01-14
        相关资源
        最近更新 更多