代理模式是结构型设计模式 的一种,核心思想:给一个对象找一个 "代理人",让代理人代替原对象处理请求,原对象只做核心业务逻辑。
代理模式在Java的使用
声明式事务 @Transactional、AOP 切面增强 @Aspect等等
- 日志记录
- 权限校验
- 耗时统计
- 参数校验
- 异常统一处理
代理对象负责重复的非业务操作,如记录前后日志、权限校验。原对象只需要关注核心业务。
一、核心概念
- 抽象主题(Subject):定义原对象和代理对象的公共接口(同时做的事情)
- 真实主题(RealSubject):真正做事的原对象(例如项目中的核心业务逻辑)
- 代理(Proxy):代替原对象处理请求,可附加额外功能(给业务加的日志等功能)
- 客户端(Client):使用代理对象,不直接接触原对象(调用代理对象,先执行完代理对象的操作再执行核心业务逻辑)
核心特点
- 不修改原对象代码:通过代理扩展功能(开闭原则)
- 职责分离:原对象只做核心业务,代理做日志、权限、缓存等附加操作
- 保护 / 控制访问:代理可以拦截、过滤对原对象的请求
二、两种代理实现方式
1. 静态代理(手动写代理类)
适合代理对象固定的场景,代码写死,编译时就确定代理关系。
代码示例
java
/**
* @author T
* @version 1.0 2026-04-19
*/
public interface UserService {
void deleteUser(Long userId);
}
public class UserServiceImpl implements UserService{
@Override
public void deleteUser(Long userId) {
// 这里我们来写核心的业务逻辑
System.out.println("删除用户id为"+userId+"的用户!");
}
}
public class ProxyServiceImpl implements UserService{
private UserService userService;
public ProxyServiceImpl(UserService userService){
this.userService = userService;
}
@Override
public void deleteUser(Long userId) {
System.out.println("执行删除前的日志记录、权限校验");
userService.deleteUser(userId);
System.out.println("执行删除成功后的操作");
}
}
public class Client {
public static void main(String[] args) {
UserService proxy = new ProxyServiceImpl(new UserServiceImpl());
proxy.deleteUser(1L);
}
}
输出:

2. 动态代理(自动生成代理类)
不用手动写代理类,运行时自动生成代理对象,适合批量代理多个类。Java 中常用两种:
- JDK 动态代理:JDK 动态代理通过生成"实现接口的代理类",因此必须依赖接口,否则无法代理
- CGLIB 动态代理:基于类(无需接口),通过继承 + 方法重写 + 方法拦截
JDK 动态代理示例
java
public interface UserService {
void deleteUser(Long userId);
}
public class UserServiceImpl implements UserService {
@Override
public void deleteUser(Long userId) {
// 核心业务逻辑
System.out.println("删除用户id为"+userId+"的用户!");
}
}
public class DynamicProxyFactory {
// 传入目标对象,返回 动态代理对象
public static Object getProxy(Object target) {
// 方法拦截处理器
return Proxy.newProxyInstance(
target.getClass().getClassLoader(), // 类加载器
target.getClass().getInterfaces(), // 目标对象实现的接口
(proxy, method, args) -> {
// ===================== 前置增强 =====================
System.out.println("执行删除前的日志记录、权限校验");
// ===================== 执行目标方法 =====================
Object result = method.invoke(target, args);
// ===================== 后置增强 =====================
System.out.println("执行删除成功后的操作");
return result;
}
);
}
}
输出:

CGLIB动态代理示例
java
public class UserService {
public void deleteUser(Long userId) {
System.out.println("删除用户id为"+userId+"的用户!");
}
}
public class CglibProxyFactory {
public static UserService getProxy(Class<?> clazz) {
Enhancer enhancer = new Enhancer();
// 继承目标类,生成子类代理
enhancer.setSuperclass(clazz);
// 设置回调拦截器
enhancer.setCallback(new UserMethodInterceptor());
return (UserService) enhancer.create();
}
}
public class UserMethodInterceptor 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;
}
}
public class Client {
public static void main(String[] args) {
// 直接获取代理对象,无需接口
UserService proxy = CglibProxyFactory.getProxy(UserService.class);
proxy.deleteUser(1L);
}
}
结果

三、代理模式的典型应用场景
- 远程代理:代理远程对象(比如 RPC 框架、微服务调用)
- 虚拟代理:延迟创建耗资源的对象(比如:网页先显示图片占位符,加载完再显示真实图片)
- 安全代理:控制访问权限(比如:接口权限校验)
- 日志 / 监控代理:统一记录日志、统计接口耗时
- 缓存代理:给方法加缓存,避免重复执行
- Spring AOP:底层就是动态代理,实现切面编程(日志、事务、权限)
四、静态代理 vs 动态代理
| 特点 | 静态代理 | 动态代理 |
|---|---|---|
| 实现方式 | 手动编写代理类 | 运行时自动生成代理对象 |
| 灵活性 | 低(一个类一个代理) | 高(一个代理类代理多个类) |
| 效率 | 编译期确定,性能高 | 运行时生成,略低 |
| 适用场景 | 代理对象少且固定 | 批量代理、框架开发 |
五、CGlib和JDK动态代理
-
JDK 动态代理
- 基于接口实现
- 底层反射
- 目标类可以不用继承
- JDK 动态代理通过生成"实现接口的代理类",因此必须依赖接口,否则无法代理
-
CGLIB 动态代理
- 基于继承子类实现
- 无需接口
- 不能代理
final类、final方法 - Spring 没有接口时自动用 CGLIB
六、总结
- 代理模式 = 代理人 + 真实对象,代理帮原对象处理杂事,原对象专注核心业务
- 核心价值:不修改原代码,扩展功能(日志、权限、缓存等)
- 两种实现:静态代理(简单)、动态代理(灵活,Spring 底层核心)