结构型-代理模式
2026/1/15大约 2 分钟Java设计模式结构型模式代理模式Java设计模式面向对象架构设计最佳实践代码优化
概述
代理模式(Proxy Pattern)为其他对象提供一种代理以控制对这个对象的访问。在某些情况下,一个对象不适合或者不能直接引用另一个对象,而代理对象可以在客户端和目标对象之间起到中介的作用。
适用场景
- 远程代理:为一个位于不同地址空间的对象提供本地代表
- 虚拟代理:根据需要创建开销很大的对象
- 保护代理:控制对原始对象的访问
- 智能引用:在访问对象时执行一些附加操作
角色组成
- Subject(抽象主题):声明真实主题和代理的共同接口
- RealSubject(真实主题):定义代理所代表的真实对象
- Proxy(代理):保存一个引用使得代理可以访问实体
静态代理
// 抽象主题
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() {
if (realSubject == null) {
realSubject = new RealSubject();
}
preRequest();
realSubject.request();
postRequest();
}
private void preRequest() {
System.out.println("代理前置处理");
}
private void postRequest() {
System.out.println("代理后置处理");
}
}
```bash
# 输出
代理前置处理
真实对象的请求
代理后置处理JDK 动态代理
public interface UserService {
void save(String name);
}
public class UserServiceImpl implements UserService {
@Override
public void save(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());
Object result = method.invoke(target, args);
System.out.println("方法调用后: " + method.getName());
return result;
}
}
// 使用
public class Client {
public static void main(String[] args) {
UserService target = new UserServiceImpl();
UserService proxy = (UserService) Proxy.newProxyInstance(
target.getClass().getClassLoader(),
target.getClass().getInterfaces(),
new LogHandler(target)
);
proxy.save("张三");
}
}CGLIB 动态代理
public class UserDao {
public void save() {
System.out.println("保存数据");
}
}
// CGLIB 代理
public class CglibProxy implements MethodInterceptor {
public Object getProxy(Class<?> clazz) {
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(clazz);
enhancer.setCallback(this);
return enhancer.create();
}
@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;
}
}类图
JDK vs CGLIB
| 特性 | JDK 动态代理 | CGLIB |
|---|---|---|
| 实现方式 | 接口 | 继承 |
| 目标类要求 | 必须实现接口 | 无需接口 |
| 性能 | 较低 | 较高 |
| final 类 | 可以 | 不可以 |
Spring AOP 中的代理
// Spring 自动选择代理方式
// 有接口 -> JDK 动态代理
// 无接口 -> CGLIB 代理
@Aspect
@Component
public class LogAspect {
@Before("execution(* com.example.service.*.*(..))")
public void before(JoinPoint joinPoint) {
System.out.println("方法执行前: " + joinPoint.getSignature().getName());
}
}优缺点
优点:
- 职责清晰
- 高扩展性
- 智能化
缺点:
- 增加系统复杂度
- 可能造成请求处理速度变慢
