Java设计模式之代理模式详解

Java设计模式之代理模式详解


一、代理模式核心思想

核心目标为其他对象提供代理以控制访问,在不修改原始对象的基础上增强功能。如同明星经纪人,控制外界与目标对象的交互过程。


二、代理模式类图(Mermaid)

1. 静态代理

委托调用 <<interface>> Subject +request() RealSubject +request() Proxy -realSubject: RealSubject +request()

2. JDK动态代理

<<interface>> InvocationHandler +invoke(Object proxy, Method method, Object\[\] args) Proxy +newProxyInstance(ClassLoader, Class\[\], InvocationHandler) Client


三、三种代理类型对比

代理类型 实现方式 特点
静态代理 手动编写代理类 简单直观,但类文件数量多
JDK动态代理 反射+接口代理 无需手动编码,但需实现接口
CGLIB代理 字节码增强(继承方式) 可代理无接口类,final类除外

四、代码实现示例

1. 静态代理示例(数据库查询场景)

java 复制代码
// 抽象主题
interface DatabaseQuery {
    String query(String sql);
}

// 真实主题
class RealDatabaseQuery implements DatabaseQuery {
    public String query(String sql) {
        // 实际数据库操作
        return "Result of: " + sql;
    }
}

// 代理类
class DatabaseQueryProxy implements DatabaseQuery {
    private RealDatabaseQuery realQuery = new RealDatabaseQuery();
    
    public String query(String sql) {
        checkAccess();
        String result = realQuery.query(sql);
        logQuery(sql);
        return result;
    }
    
    private void checkAccess() {
        System.out.println("校验访问权限...");
    }
    
    private void logQuery(String sql) {
        System.out.println("记录查询日志: " + sql);
    }
}

// 客户端调用
DatabaseQuery query = new DatabaseQueryProxy();
System.out.println(query.query("SELECT * FROM users"));

2. JDK动态代理示例(性能监控场景)

java 复制代码
// 抽象主题
interface UserService {
    void addUser(String name);
}

// 真实主题
class UserServiceImpl implements UserService {
    public void addUser(String name) {
        System.out.println("添加用户: " + name);
    }
}

// InvocationHandler实现
class PerformanceHandler implements InvocationHandler {
    private Object target;
    
    public PerformanceHandler(Object target) {
        this.target = target;
    }
    
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        long start = System.currentTimeMillis();
        Object result = method.invoke(target, args);
        long duration = System.currentTimeMillis() - start;
        System.out.println(method.getName() + "方法耗时: " + duration + "ms");
        return result;
    }
}

// 客户端调用
UserService realService = new UserServiceImpl();
UserService proxy = (UserService) Proxy.newProxyInstance(
    UserService.class.getClassLoader(),
    new Class[]{UserService.class},
    new PerformanceHandler(realService)
);

proxy.addUser("张三");  // 输出执行耗时

五、模式优缺点分析

✅ 优势

  • 职责清晰:代理类专注控制逻辑,真实类专注业务
  • 扩展性强:无侵入式增强功能(日志、权限、缓存等)
  • 保护目标对象:限制直接访问敏感操作

❌ 缺点

  • 系统复杂度增加:引入额外代理层
  • 性能损耗:动态代理基于反射,执行效率略低

六、典型应用场景

  1. 远程代理:RMI(远程方法调用)
  2. 虚拟代理:延迟加载大文件/图片
  3. 保护代理:权限控制(如Spring Security)
  4. 缓存代理:缓存请求结果(如MyBatis缓存)
  5. AOP实现:Spring的事务管理/@Async异步处理

七、Mermaid序列图(动态代理流程)

Client Proxy InvocationHandler RealSubject methodCall() invoke() method.invoke() Client Proxy InvocationHandler RealSubject


八、代理模式 vs 其他模式

对比模式 核心区别
装饰器模式 增强对象功能,保持接口一致性
适配器模式 改变对象接口
外观模式 简化复杂子系统接口

九、Spring框架中的代理应用

Spring AOP代理机制

classDiagram class UserServiceImpl { +addUser() } class ProxyFactoryBean { -target -interceptorNames } class MethodInterceptor { <<interface>> +invoke() } UserServiceImpl --> ProxyFactoryBean : 目标对象 ProxyFactoryBean --> MethodInterceptor : 增强逻辑 note for ProxyFactoryBean "默认JDK动态代理\n若无接口使用CGLIB"

十、常见问题解答

Q1:动态代理性能如何优化?

  • 缓存代理对象:避免重复创建
  • 使用CGLIB的FastClass机制:减少反射调用
  • 关闭调试信息System.setProperty(DebuggingClassWriter.DEBUG_LOCATION_PROPERTY, "")

Q2:如何强制使用CGLIB代理?

Spring配置方式:

java 复制代码
@Configuration
@EnableAspectJAutoProxy(proxyTargetClass = true)
public class AppConfig {}

Q3:代理模式如何实现懒加载?

java 复制代码
class LazyInitProxy implements ImageLoader {
    private RealImageLoader realLoader;
    
    public void load(String path) {
        if (realLoader == null) {
            realLoader = new RealImageLoader(); // 延迟初始化
        }
        realLoader.load(path);
    }
}
相关推荐
vx-程序开发5 分钟前
【毕设分享】springboot废品上门回收微信小程序---附源码94491
java·spring boot·毕业设计·源码·课程设计·毕设·大作业
宸津-代码粉碎机6 分钟前
Spring AI 高危CVE漏洞深度复盘|生产禁跑版本汇总+临时防御+修复方案
java·大数据·人工智能·python·spring
敲代码的嘎仔35 分钟前
用 Redis 合并写 + DelayQueue 延迟检测,把视频播放进度写库频率降到 1/60
java·开发语言·数据库·redis·缓存·音视频·高并发
youyou-06061 小时前
AUTOSAR‑COM 常见问题 QA (1)
java·linux·服务器·单片机·汽车
谢亮_vipxieliang1 小时前
ValidX时间段验证详解:ISO 8601标准与简化格式
java·spring boot·后端·spring·spring cloud·hibernate
Lsetea1 小时前
Java 请求 HTTPS 报 PKIX path building failed:从证书链到 truststore 的完整排查
java·https·ssl证书·keytool·truststore
蓝桉柒72 小时前
java判断语句
java·开发语言
Zane19942 小时前
String::compareTo凭什么能当参数传?方法引用的四种形式讲透
java·后端
青山木2 小时前
Hot 100 --- 打家劫舍
java·数据结构·算法·leetcode·动态规划
敲代码的嘎仔2 小时前
28届后端开发-百人小厂面试题
java·后端·面试·程序员·秋招·实习·转正