引言
代理模式(Proxy Design Pattern)在不改变原始类(或叫被代理类)代码的情况下,通过引入代理类来给原始类附加功能。
代理模式的关键角色包括:
- 抽象主题(Subject):定义了目标对象和代理对象的共同接口,这样一来在任何可以使用目标对象的地方都可以使用代理对象。
- 目标对象(Real Subject):也称为被代理对象,是具体业务逻辑的实际执行者。
- 代理对象(Proxy):负责代理目标对象,它持有对目标对象的引用,并在其自身的方法中调用目标对象的方法,同时还可以在调用前后进行一些其他的操作。
应用场景
代理模式可以应用于许多场景,以下是几个常见的应用场景:
- 远程代理(Remote Proxy):代理模式可以用来在客户端和远程对象之间建立代理对象,隐藏了实际的网络通信细节。客户端通过代理对象调用远程对象的方法,而无需关心网络通信的具体实现。
- 虚拟代理(Virtual Proxy):代理模式可以用来延迟加载资源密集或耗时的对象,只有当真正需要使用这些对象时,才会创建并加载真实的对象。虚拟代理可以在一定程度上提升系统性能和响应速度。
- 安全代理(Protection Proxy):代理模式可以用来控制对敏感对象的访问权限。代理对象可以在调用目标对象方法之前检查权限,如果没有足够的权限,则不允许访问。
- 缓存代理(Caching Proxy):代理模式可以用来缓存目标对象的计算结果,当相同的请求再次到达时,可以直接返回缓存的结果,避免重复计算,提高系统性能。
- 日志记录代理(Logging Proxy):代理模式可以在目标对象的方法执行前后进行日志记录,用于跟踪和调试系统运行过程中的操作。
- AOP(面向切面编程):代理模式是实现AOP的基础,可以通过代理对象在目标对象的方法执行前后插入切面逻辑,例如日志、事务管理等。
需要注意的是,代理模式并非适用于所有情况。在某些场景下,代理模式可能引入额外的复杂性和性能开销,需要根据具体问题和需求来决定是否使用代理模式。
编程示例
代理模式的实现方式有多种,常见的有静态代理和动态代理两种形式:
- 静态代理:在编译时期就已经确定代理关系,代理类和目标类的关系在代码中明确指定。
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 
 | public interface Subject {
 void request();
 }
 
 
 @Slf4j
 public class RealSubject implements Subject {
 @Override
 public void request() {
 
 LOGGER.info("开始处理请求");
 }
 }
 
 @Slf4j
 public class Proxy implements Subject {
 private Subject realSubject;
 
 public Proxy(Subject realSubject) {
 this.realSubject = realSubject;
 }
 
 @Override
 public void request() {
 LOGGER.info("前置处理逻辑");
 
 realSubject.request();
 
 LOGGER.info("后置处理逻辑");
 }
 }
 
 
 public class Client {
 public static void main(String[] args) {
 Subject realSubject = new RealSubject();
 Subject proxy = new Proxy(realSubject);
 
 proxy.request();
 }
 }
 
 | 
- 动态代理:在运行时动态生成代理类,无需提前编写代理类。Java 中的动态代理主要通过 java.lang.reflect.Proxy类和java.lang.reflect.InvocationHandler接口实现。
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 
 | public interface Subject {
 void request();
 }
 
 
 @Slf4j
 public class RealSubject implements Subject {
 @Override
 public void request() {
 
 LOGGER.info("开始处理请求");
 }
 }
 
 public class DynamicProxy implements InvocationHandler {
 private Object target;
 
 public DynamicProxy(Object target) {
 this.target = target;
 }
 
 @Override
 public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
 
 LOGGER.info("前置处理逻辑");
 Object result = method.invoke(target, args);
 
 LOGGER.info("后置处理逻辑");
 return result;
 }
 }
 
 
 public class Client {
 public static void main(String[] args) {
 Subject realSubject = new RealSubject();
 
 InvocationHandler handler = new DynamicProxy(realSubject);
 Subject proxy = (Subject) Proxy.newProxyInstance(
 realSubject.getClass().getClassLoader(),
 realSubject.getClass().getInterfaces(),
 handler
 );
 
 proxy.request();
 }
 }
 
 | 
以上内容基于GPT创建和整理。
参考
关于作者
来自一线全栈程序员nine的八年探索与实践,持续迭代中。欢迎关注“雨林寻北”或添加个人卫星codetrend(备注技术)。