# 代理模式
# 简要回答
- 代理模式(Proxy Pattern)是一种结构型设计模式,其主要目的是在访问某个对象时引入一种代理对象,通过代理对象控制对原始对象的访问。代理模式可以用于实现懒加载、控制访问、监控对象等场景。
- 优点:代理模式不修改目标对象的原有代码,通过代理对象实现在核心方法前后添加额外的业务逻辑,符合设计模式的开闭原则和单一职责原则。
- 缺点:静态代理会增加类的数量,一个真实对象对应一个代理对象,业务复杂时代理类数量会很多。
# 详细回答
- 代理模式可以由抽象主题(Subject)、具体主题(RealSubject)、代理(Proxy)三部分组成。抽象主题定义了代理对象和真实对象的共同接口,使得代理对象能够替代真实对象,客户端只通过该接口与对象交互;真实主题则是实际执行业务逻辑的对象,是代理模式中被代理的对象,实现抽象主题的接口,关注核心业务代码编写;而代理持有一个指向真实主题的引用,也会实现抽象主题的接口,负责执行增强逻辑,可以控制对真实主题的访问,并在需要时负责创建或删除真实主题的实例。
- 代理模式的执行流程如下:首先由客户端发起业务方法调用,调用代理对象的对应方法;代理对象会执行权限校验、日志打印等前置增强逻辑,然后通过持有的引用调用真实对象的核心业务方法,将执行结果返回给代理对象后,代理对象执行后置增强逻辑,将最终结果返回给客户端,使用代理模式时客户端只和代理对象交互。
- 代理模式可以分为静态代理和动态代理两类,静态代理在编译期就编写好了代理类的代码,代理类与真实类一一对应,编译完成后代理类就是一个固定的class文件。实现简单,适合业务比较固定的场景。如果抽象主题新增方法,真实类和代理类都需要同步修改,扩展性差。动态代理则是在运行期由JVM通过反射机制动态生成代理类的字节码,无需手动编写代理类代码,一个动态代理类可以为任意多个真实类提供代理服务,能够解决静态代理的扩展性问题。Java中有基于接口的JDK动态代理和基于继承实现的CGLIB动态代理。
- 代理模式有四种常见的应用类型:
- 远程代理(Remote Proxy)会对请求及其参数进行编码,并向不同地址空间中的实体发送已编码的请求,为远程对象提供本地访问。
- 虚拟代理(Virtual Proxy)可以缓存实体的附加信息以便延迟对它的访问,当创建开销很大的对象时使用。
- 保护代理(Protection Proxy)控制对原始对象的访问,检查调用者是否具有实现一个请求所必需的访问权限。
- 智能引用(Smart Reference)是调用真实的对象时,执行附加操作。
# 知识图解
- 代理模式结构图

# 示例代码
// 1. 抽象主题:统一业务接口
interface Service {
void doWork();
}
// 2. 真实主题:只负责核心业务
class RealService implements Service {
@Override
public void doWork() {
System.out.println("执行真实核心业务");
}
}
// 3. 代理主题:代理+增强逻辑,核心!
class ProxyService implements Service {
private Service realService;
// 传入真实对象
public ProxyService(Service realService) {
this.realService = realService;
}
@Override
public void doWork() {
// 前置增强
System.out.println("代理前置:权限校验/日志记录/懒加载...");
// 调用真实业务
realService.doWork();
// 后置增强
System.out.println("代理后置:缓存结果/资源释放/计数统计...");
}
}
// 4. 客户端调用
public class Client {
public static void main(String[] args) {
Service real = new RealService();
Service proxy = new ProxyService(real);
proxy.doWork(); // 只调用代理
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
# 知识扩展
- 面试官可能追问:
- Q1:代理模式和装饰者模式有什么区别?
- 代理模式和装饰者模式的设计目的与增强方式不同。
- 代理模式的核心是控制访问,代理对象会决定是否调用真实对象方法,真实对象的核心业务逻辑不变,增强逻辑则是为了辅助核心业务,如权限校验、日志记录、缓存等。
- 装饰者模式的核心是增加功能,装饰者对象会对真实对象的核心功能进行扩展,丰富核心业务。
- Q2:静态代理和动态代理有什么区别?为什么实际开发选择动态代理?
- 静态代理和动态代理的核心区别是代理类的创建时机和扩展性不同,静态代理在编译期创建,扩展性差;动态代理则是运行期反射生成,扩展性极强。在实际开发中业务会频繁迭代,新增方法,使用动态代理在新增真实对象时无需修改任何代码,能大幅降低维护成本。
- Q3:你在项目中使用过代理模式吗?
- 使用过。我在项目中实现接口的统一日志和权限校验时,使用动态代理为所有业务生成代理对象,在调用核心方法前会先对用户token、接口访问权限等进行判断。这样所有的业务类只需要写核心业务代码,无需关心日志与权限,代码整洁且可扩展性强。
- Q4:Spring中哪里使用了代理模式?
- Spring的声明式事务是基于代理模式实现的,在业务方法上添加@Transactional注解,Spring容器会为这个类生成一个代理对象,代理对象会拦截对这个类的方法调用,并在调用之前执行事务管理逻辑,帮助我们完成事务的开启、提交和回滚。
评论
验证登录状态...