dynamic proxy类是实现接口列表的类 在运行时指定,以便通过其中一个方法调用 将对类的实例上的接口进行编码和分派 通过统一的界面到另一个对象。它可以用来 为没有的接口列表创建一个类型安全的代理对象 需要预生成代理类。动态代理类是 对需要提供类型安全的应用程序或库有用 在呈现接口的对象上反射调度调用 蜜蜂
上面的图片很好,但为什么我们使用动态代理呢?
有没有一个简单的例子可以在现实世界中使用,以获得更多感知?
答案 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;
}
}