1.概要
代理设计模式是一种结构型设计模式,用于提供对象的替代品或占位符。在代理模式中,创建具有现有对象功能的对象,以向外部提供接口。代理控制着对原对象的访问,并允许在请求提交给对象前后进行一些处理。代理模式主要有三种形式:
- 静态代理:在编译期就已确定被代理的对象。代理类和被代理类共同实现一个接口或继承同一个类。
- 动态代理:在运行时通过反射机制实现,能够代理各种类型的对象。
- Cglib代理:属于动态代理的一种,能够在内存动态创建对象,无需实现接口。
使用场景
- 延迟初始化(虚拟代理):当有一个重量级的服务对象,但并不总是需要在程序启动时加载,可以使用代理来延迟初始化。代理对象在需要时才真正创建和加载原始对象,从而节省系统资源。
- 访问控制(保护代理):代理模式可以用于限制对某个对象的访问,实现访问控制和权限管理。只有经过授权的代理对象才能访问原始对象的某些功能。
- 权限控制:代理可以用来检查用户的权限,确保用户有权执行某些操作,例如数据库访问、文件操作等。
- 记录日志:代理可以用于记录方法的调用日志,包括方法的参数、返回值等信息,用于调试和监控应用程序。
- 缓存代理:代理可以缓存原始对象的结果,以提高性能。如果某个操作的结果已经被计算过,代理可以返回缓存的结果而不是重新计算。
2.详细内容
2.1静态代理
静态代理是代理设计模式的一种形式,它在编译期间就已经确定了被代理对象和代理对象。在静态代理中,代理类和被代理类共同实现同一个接口或者继承同一个父类。代理类负责控制对被代理对象的访问,可以在调用被代理对象的方法前后执行一些额外的操作,例如日志记录、性能监控、安全控制等。
静态代理的特点是代理类在编译期就已经存在,因此它的结构相对固定,不太灵活。代理类需要手动编写,通常一个代理类只能代理一个接口或者父类。
代码示例
代码语言:javascript复制// 接口定义
public interface ISubject
{
void Request();
}
// 具体实现类
public class RealSubject : ISubject
{
public void Request()
{
Console.WriteLine("RealSubject handles the request.");
}
}
// 代理类
public class Proxy : ISubject
{
private RealSubject realSubject;
public Proxy()
{
realSubject = new RealSubject();
}
public void Request()
{
// 可以在调用真实对象之前或之后执行一些额外操作
Console.WriteLine("Proxy handles the request.");
realSubject.Request();
}
}
// 客户端代码
class Program
{
static void Main(string[] args)
{
ISubject proxy = new Proxy();
proxy.Request();
}
}
2.2 动态代理
动态代理是代理设计模式的一种实现方式,允许在运行时创建代理对象,而无需预先编译好的类。它常用于实现横切关注点(cross-cutting concerns)的功能,比如日志、安全性检查、性能监测等。
代码语言:javascript复制using System;
using System.Reflection;
public interface IService
{
void DoSomething();
}
public class RealService : IService
{
public void DoSomething()
{
Console.WriteLine("RealService is doing something.");
}
}
public class ProxyGenerator
{
public static T CreateProxy<T>(T target) where T : class
{
return (T)Activator.CreateInstance(typeof(T), new Proxy(target));
}
private class Proxy : DispatchProxy
{
private object _target;
public Proxy(object target)
{
_target = target;
}
protected override object Invoke(MethodInfo targetMethod, object[] args)
{
Console.WriteLine($"Intercepting {targetMethod.Name}");
var result = targetMethod.Invoke(_target, args);
Console.WriteLine($"Finished intercepting {targetMethod.Name}");
return result;
}
}
}
class Program
{
static void Main(string[] args)
{
IService realService = new RealService();
IService proxyService = ProxyGenerator.CreateProxy(realService);
proxyService.DoSomething();
}
}
2.3 Cglib代理
它是一种基于字节码生成技术的代理模式。Cglib代理不要求被代理的类实现接口,而是通过生成被代理类的子类来实现代理。这种方式也是一种“动态代理”。
代码语言:javascript复制using System;
using System.Reflection;
using System.Reflection.Emit;
public class ProxyGenerator
{
public static T CreateProxy<T>() where T : class, new()
{
var dynamicMethod = new DynamicMethod("CglibProxy", typeof(T), Type.EmptyTypes, typeof(ProxyGenerator).Module);
var ilGenerator = dynamicMethod.GetILGenerator();
// Create a new instance of the target class
ilGenerator.Emit(OpCodes.Newobj, typeof(T).GetConstructor(Type.EmptyTypes));
// Return the new instance as the result of the method
ilGenerator.Emit(OpCodes.Ret);
// Create a delegate to the dynamic method
var methodDelegate = (Func<T>)dynamicMethod.CreateDelegate(typeof(Func<T>));
// Return the proxy instance
return methodDelegate();
}
}
public class TargetClass
{
public void DoSomething()
{
Console.WriteLine("TargetClass is doing something.");
}
}
class Program
{
static void Main(string[] args)
{
// Create a Cglib proxy for TargetClass
TargetClass proxy = ProxyGenerator.CreateProxy<TargetClass>();
// Call the method on the proxy
proxy.DoSomething();
}
}