代理模式 (Proxy)
📖 通俗理解
你要租房,但不想自己到处找房源、谈价格、签合同。怎么办?
找个房产中介!中介帮你找房、带看、谈价格、办手续,你只需要付钱入住。
代理模式就是:为对象提供一个代理,控制对这个对象的访问。
🎯 解决什么问题?
场景:
- 访问对象前需要做一些控制(权限、日志、缓存)
- 对象创建开销很大,希望延迟创建
- 远程对象需要本地代理
🌰 生活中的例子
- 房产中介:代理房东出租房子
- 明星经纪人:代理明星接洽工作
- VPN 代理:代理访问网络
- 信用卡:代理你的银行账户消费
💻 Java 代码实现
方式一:静态代理
/**
* 主题接口
*/
public interface Subject {
void request();
}
/**
* 真实主题
*/
public class RealSubject implements Subject {
@Override
public void request() {
System.out.println("真实对象处理请求...");
}
}
/**
* 代理类
*/
public class Proxy implements Subject {
private RealSubject realSubject;
@Override
public void request() {
// 前置处理
System.out.println("代理:权限检查...");
System.out.println("代理:记录日志...");
// 延迟创建真实对象
if (realSubject == null) {
realSubject = new RealSubject();
}
// 调用真实对象
realSubject.request();
// 后置处理
System.out.println("代理:清理工作...");
}
}
使用:
public class Client {
public static void main(String[] args) {
Subject subject = new Proxy();
subject.request();
}
}
方式二:JDK 动态代理 ⭐
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
/**
* 服务接口
*/
public interface UserService {
void addUser(String name);
void deleteUser(String name);
}
/**
* 真实服务
*/
public class UserServiceImpl implements UserService {
@Override
public void addUser(String name) {
System.out.println("添加用户: " + name);
}
@Override
public void deleteUser(String name) {
System.out.println("删除用户: " + name);
}
}
/**
* 动态代理处理器
*/
public class LogHandler implements InvocationHandler {
private Object target;
public LogHandler(Object target) {
this.target = target;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// 前置增强
System.out.println("[日志] 调用方法: " + method.getName());
long start = System.currentTimeMillis();
// 调用真实方法
Object result = method.invoke(target, args);
// 后置增强
long end = System.currentTimeMillis();
System.out.println("[日志] 方法执行耗时: " + (end - start) + "ms\n");
return result;
}
/**
* 创建代理对象
*/
@SuppressWarnings("unchecked")
public static <T> T createProxy(T target) {
return (T) Proxy.newProxyInstance(
target.getClass().getClassLoader(),
target.getClass().getInterfaces(),
new LogHandler(target)
);
}
}
使用:
public class Client {
public static void main(String[] args) {
UserService realService = new UserServiceImpl();
UserService proxyService = LogHandler.createProxy(realService);
proxyService.addUser("张三");
proxyService.deleteUser("李四");
}
}
输出:
[日志] 调用方法: addUser
添加用户: 张三
[日志] 方法执行耗时: 1ms
[日志] 调用方法: deleteUser
删除用户: 李四
[日志] 方法执行耗时: 0ms
方式三:CGLIB 动态代理
CGLIB 可以代理没有接口的类:
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
/**
* 没有接口的类
*/
public class OrderService {
public void createOrder(String orderId) {
System.out.println("创建订单: " + orderId);
}
}
/**
* CGLIB 方法拦截器
*/
public class CglibInterceptor implements MethodInterceptor {
@Override
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;
}
@SuppressWarnings("unchecked")
public static <T> T createProxy(Class<T> clazz) {
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(clazz);
enhancer.setCallback(new CglibInterceptor());
return (T) enhancer.create();
}
}
// 使用
OrderService proxy = CglibInterceptor.createProxy(OrderService.class);
proxy.createOrder("ORD001");
🔥 常见代理类型
| 代理类型 | 说明 | 例子 |
|---|---|---|
| 远程代理 | 为远程对象提供本地代理 | RMI、RPC |
| 虚拟代理 | 延迟创建开销大的对象 | 懒加载图片 |
| 保护代理 | 控制对象的访问权限 | 权限校验 |
| 缓存代理 | 为结果提供缓存 | 数据缓存 |
✅ 适用场景
- AOP 切面编程:日志、事务、权限
- 延迟加载:大对象的延迟初始化
- 远程调用:RPC 框架
- 访问控制:权限检查
⚠️ JDK 代理 vs CGLIB
| 对比项 | JDK 动态代理 | CGLIB |
|---|---|---|
| 要求 | 必须有接口 | 可以没有接口 |
| 原理 | 实现接口 | 继承类 |
| 性能 | 稍慢 | 稍快 |
小结
代理模式的核心:为对象提供一个替身,控制对这个对象的访问。
Spring AOP 底层就是使用代理模式(JDK 动态代理 + CGLIB)。
👉 下一篇:责任链模式
