为什么我们使用动态代理

时间:2013-08-21 06:39:19

标签: c# java proxy

  

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

上面的图片很好,但为什么我们使用动态代理呢?

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

4 个答案:

答案 0 :(得分:2)

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

几个例子:

  • Hibernate和Entity Framework等ORM执行此操作以围绕代码优先设计提供持久性实现。核心域类是在不知道其持久性的情况下构建的,并且框架在启动时包装或扩展这些类以处理实际的实现。

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

答案 1 :(得分:1)

想象一下,您有两个对象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());

答案 2 :(得分:0)

答案 3 :(得分:-1)

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;  
    }  
}