Java设计模式之代理模式详解
一、代理模式核心思想
核心目标:为其他对象提供代理以控制访问,在不修改原始对象的基础上增强功能。如同明星经纪人,控制外界与目标对象的交互过程。
二、代理模式类图(Mermaid)
1. 静态代理
2. JDK动态代理
三、三种代理类型对比
代理类型 | 实现方式 | 特点 |
---|---|---|
静态代理 | 手动编写代理类 | 简单直观,但类文件数量多 |
JDK动态代理 | 反射+接口代理 | 无需手动编码,但需实现接口 |
CGLIB代理 | 字节码增强(继承方式) | 可代理无接口类,final类除外 |
四、代码实现示例
1. 静态代理示例(数据库查询场景)
// 抽象主题
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动态代理示例(性能监控场景)
// 抽象主题
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("张三"); // 输出执行耗时
五、模式优缺点分析
✅ 优势
- 职责清晰:代理类专注控制逻辑,真实类专注业务
- 扩展性强:无侵入式增强功能(日志、权限、缓存等)
- 保护目标对象:限制直接访问敏感操作
❌ 缺点
- 系统复杂度增加:引入额外代理层
- 性能损耗:动态代理基于反射,执行效率略低
六、典型应用场景
- 远程代理:RMI(远程方法调用)
- 虚拟代理:延迟加载大文件/图片
- 保护代理:权限控制(如Spring Security)
- 缓存代理:缓存请求结果(如MyBatis缓存)
- AOP实现:Spring的事务管理/@Async异步处理
七、Mermaid序列图(动态代理流程)
八、代理模式 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配置方式:
@Configuration
@EnableAspectJAutoProxy(proxyTargetClass = true)
public class AppConfig {}
Q3:代理模式如何实现懒加载?
class LazyInitProxy implements ImageLoader {
private RealImageLoader realLoader;
public void load(String path) {
if (realLoader == null) {
realLoader = new RealImageLoader(); // 延迟初始化
}
realLoader.load(path);
}
}