温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

什么是静态代理与动态代理

发布时间:2021-10-21 09:46:47 来源:亿速云 阅读:149 作者:iii 栏目:编程语言
# 什么是静态代理与动态代理 ## 目录 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("[静态代理]操作后事务处理"); } } 

优缺点分析

优势: - 符合开闭原则:无需修改目标对象 - 职责清晰:辅助逻辑集中在代理类 - 编译期检查:类型安全有保障

局限性: - 类爆炸问题:每个服务都需要对应代理类 - 接口耦合:必须实现相同接口 - 维护成本:接口变更需同步修改代理类


三、动态代理深入解析

JDK动态代理机制

基于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统一处理调用

CGLIB动态代理

通过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类/方法

四、应用场景分析

静态代理适用场景

  1. 简单明确的扩展需求
  2. 代理类需要特殊定制
  3. 目标对象数量有限的情况

动态代理经典用例

  1. Spring AOP实现
  2. RPC框架调用拦截
  3. 全局性功能增强(如日志、事务)
  4. MyBatis Mapper接口实现

五、Spring框架中的代理应用

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图示、性能测试数据及详细案例分析)

向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

AI