Java 代理模式 详解

代理模式详解

一、代理模式概述

代理模式(Proxy Pattern)是一种结构型设计模式,它为其他对象提供一种代理以控制对这个对象的访问。代理对象在客户端和目标对象之间起到中介作用,可以在不改变原始类代码的情况下增加额外功能。

核心特点

  • 控制访问:控制对目标对象的访问权限
  • 功能增强:在不修改目标对象的前提下增加额外功能
  • 解耦:客户端与目标对象解耦
  • 透明性:代理对象与目标对象实现相同接口

二、代理模式的类型

1. 静态代理

基本实现
复制代码
// 抽象主题接口
public interface Subject {
    void request();
}

// 真实主题
public class RealSubject implements Subject {
    public void request() {
        System.out.println("真实主题处理请求");
    }
}

// 代理类
public class Proxy implements Subject {
    private RealSubject realSubject;
    
    public void request() {
        if (realSubject == null) {
            realSubject = new RealSubject();
        }
        preRequest();
        realSubject.request();
        postRequest();
    }
    
    private void preRequest() {
        System.out.println("代理预处理");
    }
    
    private void postRequest() {
        System.out.println("代理后续处理");
    }
}

// 使用示例
Subject proxy = new Proxy();
proxy.request();

2. 动态代理

JDK动态代理实现
复制代码
import java.lang.reflect.*;

// 动态代理处理器
public class DynamicProxyHandler implements InvocationHandler {
    private Object target;
    
    public DynamicProxyHandler(Object target) {
        this.target = target;
    }
    
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("动态代理预处理");
        Object result = method.invoke(target, args);
        System.out.println("动态代理后续处理");
        return result;
    }
}

// 使用示例
RealSubject realSubject = new RealSubject();
Subject proxy = (Subject) Proxy.newProxyInstance(
    realSubject.getClass().getClassLoader(),
    realSubject.getClass().getInterfaces(),
    new DynamicProxyHandler(realSubject)
);
proxy.request();

三、代理模式的应用场景

1. 远程代理(RMI示例)

复制代码
// 远程接口
public interface RemoteService extends Remote {
    String getData() throws RemoteException;
}

// 远程服务实现
public class RemoteServiceImpl extends UnicastRemoteObject implements RemoteService {
    public RemoteServiceImpl() throws RemoteException {}
    
    public String getData() throws RemoteException {
        return "远程数据";
    }
}

// 客户端使用远程代理
RemoteService service = (RemoteService) Naming.lookup("rmi://localhost/RemoteService");
String data = service.getData();

2. 虚拟代理(延迟加载)

复制代码
public class ImageProxy implements Image {
    private String filename;
    private RealImage realImage;
    
    public ImageProxy(String filename) {
        this.filename = filename;
    }
    
    public void display() {
        if (realImage == null) {
            realImage = new RealImage(filename); // 延迟加载
        }
        realImage.display();
    }
}

3. 保护代理(访问控制)

复制代码
public class ProtectionProxy implements SensitiveOperation {
    private RealSensitiveOperation realOperation;
    private String userRole;
    
    public ProtectionProxy(String userRole) {
        this.userRole = userRole;
    }
    
    public void operation() {
        if (!"ADMIN".equals(userRole)) {
            throw new SecurityException("无权限访问");
        }
        if (realOperation == null) {
            realOperation = new RealSensitiveOperation();
        }
        realOperation.operation();
    }
}

4. 智能引用代理

复制代码
public class SmartReferenceProxy implements DatabaseConnection {
    private RealDatabaseConnection realConnection;
    private int referenceCount = 0;
    
    public Connection getConnection() {
        if (realConnection == null) {
            realConnection = new RealDatabaseConnection();
        }
        referenceCount++;
        return realConnection.getConnection();
    }
    
    public void release() {
        if (--referenceCount == 0 && realConnection != null) {
            realConnection.close();
            realConnection = null;
        }
    }
}

四、代理模式的变体

1. CGLIB动态代理(无需接口)

复制代码
import net.sf.cglib.proxy.*;

public class CglibProxy implements MethodInterceptor {
    public Object getProxy(Class clazz) {
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(clazz);
        enhancer.setCallback(this);
        return enhancer.create();
    }
    
    public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
        System.out.println("CGLIB代理预处理");
        Object result = proxy.invokeSuper(obj, args);
        System.out.println("CGLIB代理后续处理");
        return result;
    }
}

// 使用示例
RealSubject proxy = (RealSubject) new CglibProxy().getProxy(RealSubject.class);
proxy.request();

2. Spring AOP代理

复制代码
@Aspect
@Component
public class LoggingAspect {
    @Before("execution(* com.example.service.*.*(..))")
    public void logBefore(JoinPoint joinPoint) {
        System.out.println("方法调用前: " + joinPoint.getSignature().getName());
    }
}

五、代理模式的优缺点

优点

  1. 职责清晰:代理对象专注于控制访问
  2. 扩展性好:不修改目标对象即可增加功能
  3. 保护目标对象:控制对敏感对象的访问
  4. 性能优化:实现延迟加载和缓存

缺点

  1. 复杂度增加:引入额外抽象层
  2. 性能开销:代理调用可能增加处理时间
  3. 实现复杂:动态代理需要理解反射机制

六、最佳实践

  1. 合理选择代理类型:根据场景选择静态或动态代理
  2. 保持代理简洁:避免在代理中加入过多业务逻辑
  3. 接口设计:优先基于接口而非具体类实现代理
  4. 性能考量:对性能敏感场景评估代理开销
  5. 文档化:明确记录代理的职责和功能

七、总结

代理模式是控制对象访问的强大工具,特别适用于:

  • 需要控制对复杂或敏感对象的访问
  • 需要为对象添加额外功能而不修改其代码
  • 需要实现延迟加载或远程访问
  • 需要添加访问日志、监控等功能

在实际开发中,代理模式常见于:

  • RPC框架(如Dubbo)
  • Spring AOP实现
  • ORM框架(如Hibernate延迟加载)
  • 安全控制框架
  • 缓存实现

正确使用代理模式可以提高系统的安全性和灵活性,但需要注意不要过度使用,以免增加系统复杂性。

相关推荐
mqiqe12 分钟前
响应式流中的错误处理:Project Reactor 异常治理全体系
java·架构
我命由我1234519 分钟前
Android 开发问题:TopAppBar 和 topAppBarColors API is experimental...
android·java·java-ee·kotlin·android studio·android jetpack·android-studio
AC赳赳老秦27 分钟前
语义采集进阶实战:利用 OpenClaw AI 语义识别自动提取网页核心信息,无需手动编写选择器
java·运维·服务器·python·信息可视化·deepseek·openclaw
AI人工智能+电脑小能手31 分钟前
大白话说Java设计模式-23-桥接模式(源码剖析篇)
java·设计模式·jdbc·桥接模式·源码分析·awt·java logging
李高钢38 分钟前
C# WPF Prism 进阶(二):区域(Region)与模块化(Module)
java·前端·数据库
Logintern0940 分钟前
什么时候应该用多进程什么时候用多线程呢?
开发语言·python
long31640 分钟前
枚举(Enums)
java·开发语言·数据库
墨雨晨曦881 小时前
2026/08/15 spring AI学习总结
java·tomcat
wno7041 小时前
Spring Boot JdbcTemplate配置Druid多数据源
java·spring boot·后端
ShiXZ2131 小时前
网络调试四剑客:ping / telnet / nc / netstat 速查指令集
运维·开发语言·网络·php