您好,登录后才能下订单哦!
# 什么是静态代理与动态代理
## 目录
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进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。