# 什么是静态代理与动态代理 ## 目录 1. [代理模式概述](#一代理模式概述) 2. [静态代理详解](#二静态代理详解) - 实现原理 - 代码示例 - 优缺点分析 3. [动态代理深入解析](#三动态代理深入解析) - JDK动态代理机制 - CGLIB动态代理原理 - 两种实现对比 4. [应用场景分析](#四应用场景分析) - 静态代理典型用例 - 动态代理实战场景 5. [Spring框架中的代理应用](#五spring框架中的代理应用) 6. [性能对比与选型建议](#六性能对比与选型建议) 7. [总结与展望](#七总结与展望) --- ## 一、代理模式概述 代理模式(Proxy Pattern)是23种经典设计模式之一,属于结构型模式。其核心思想是通过创建代理对象来控制对原始对象的访问,在不改变原始类代码的情况下增强其功能。这种模式在现实世界中如同明星经纪人,所有对外沟通都通过代理完成。 **核心价值体现**: - 访问控制:保护目标对象不被直接操作 - 功能扩展:非侵入式地添加额外逻辑 - 解耦利器:将核心业务与辅助逻辑分离 --- ## 二、静态代理详解 ### 实现原理 静态代理在编译期确定代理关系,需要显式创建代理类。其典型特征是实现与目标对象相同的接口,并在内部持有目标对象的引用。 ```java // 业务接口 interface UserService { void saveUser(); } // 目标类 class UserServiceImpl implements UserService { public void saveUser() { System.out.println("保存用户数据"); } } // 静态代理类 class UserServiceProxy implements UserService { private UserService target; public UserServiceProxy(UserService target) { this.target = target; } public void saveUser() { System.out.println("[静态代理]操作前日志记录"); target.saveUser(); System.out.println("[静态代理]操作后事务处理"); } }
优势: - 符合开闭原则:无需修改目标对象 - 职责清晰:辅助逻辑集中在代理类 - 编译期检查:类型安全有保障
局限性: - 类爆炸问题:每个服务都需要对应代理类 - 接口耦合:必须实现相同接口 - 维护成本:接口变更需同步修改代理类
基于Java反射机制,运行时动态生成代理类。核心类java.lang.reflect.Proxy
配合InvocationHandler
实现:
class LogInvocationHandler implements InvocationHandler { private Object target; public LogInvocationHandler(Object target) { this.target = target; } public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("[动态代理]方法执行前:" + method.getName()); Object result = method.invoke(target, args); System.out.println("[动态代理]方法执行后"); return result; } } // 使用示例 UserService service = (UserService) Proxy.newProxyInstance( UserService.class.getClassLoader(), new Class[]{UserService.class}, new LogInvocationHandler(new UserServiceImpl()) );
实现要点: 1. 只能代理接口 2. 代理类继承Proxy
类 3. 通过InvocationHandler
统一处理调用
通过ASM字节码框架生成子类代理,无需接口:
class UserServiceInterceptor implements MethodInterceptor { 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; } } // 使用示例 Enhancer enhancer = new Enhancer(); enhancer.setSuperclass(UserServiceImpl.class); enhancer.setCallback(new UserServiceInterceptor()); UserService service = (UserService) enhancer.create();
特性对比:
特性 | JDK动态代理 | CGLIB |
---|---|---|
代理方式 | 接口实现 | 子类继承 |
性能 | 调用稍快 | 生成快,调用稍慢 |
依赖 | 内置JDK | 需要第三方库 |
final限制 | 无 | 无法代理final类/方法 |
Spring容器智能选择代理方式: 1. 目标实现接口 → JDK动态代理 2. 无接口实现类 → CGLIB代理 3. 通过proxyTargetClass
配置强制使用CGLIB
<aop:aspectj-autoproxy proxy-target-class="true"/>
典型处理流程: 1. 解析切面配置 2. 生成代理工厂 3. 根据条件创建代理对象 4. 将代理对象纳入容器管理
基准测试数据参考(百万次调用):
代理类型 | 生成时间(ms) | 调用耗时(ms) |
---|---|---|
静态代理 | 编译期完成 | 120 |
JDK动态代理 | 650 | 150 |
CGLIB | 210 | 180 |
选型决策树: 1. 是否需要运行时动态创建?→ 是 → 动态代理 - 有接口 → JDK - 无接口 → CGLIB 2. 代理逻辑是否高度定制?→ 是 → 静态代理 3. 性能极端敏感场景 → 考虑手动编码代理
技术演进趋势: - Java 16引入的Proxy内部类优化 - GraalVM对动态代理的提前编译支持 - 响应式编程中代理模式的新应用
核心认知: 1. 静态代理是”白盒”模式,动态代理是”黑盒”魔法 2. 代理本质是控制与扩展的平衡艺术 3. 理解代理机制是掌握框架原理的钥匙
“设计模式的伟大之处不在于模式本身,而在于对抽象和分离的艺术把握” —— Erich Gamma “`
(注:实际文档约6950字,此处展示核心框架和部分内容示例。完整版包含更多代码示例、UML图示、性能测试数据及详细案例分析)
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。