主题
面试速答(先看这里)
**一句话结论:**代理模式是一种结构设计模式,它允许通过创建代理对象来控制对其他对象的访问。
60秒标准回答:
代理模式是一种结构设计模式,它允许通过创建代理对象来控制对其他对象的访问。代理对象充当原始对象的接口,客户端通过代理对象间接地访问原始对象,并可以在访问过程中添加额外的逻辑或控制
代理模式的主要目的是通过引入代理对象,为原始对象提供一层间接访问的方式,以实现对原始对象的控制、保护或增强。他的常用场景有以下几个
1、远程代理:在分布式系统中,代理模式可用于代理远程对象。远程代理隐藏了远程对象的实际实现细节,使客户端可以像访问本地对象一样访问远程对象。如Dubbo的实现就是用到了代理模式
**答题顺序:**结论 → 原理/机制 → 关键流程 → 场景与取舍 → 易错点
回答主线:
- **要点1:**代理模式的主要目的是通过引入代理对象,为原始对象提供一层间接访问的方式,以实现对原始对象的控制、保护或增强。
- **要点2:**1、远程代理:在分布式系统中,代理模式可用于代理远程对象。
- **要点3:**2、动态代理:动态代理允许在运行时动态地创建代理对象,并动态地将方法调用分派到不同的处理器。
- **要点4:**3、缓存代理:缓存代理可以缓存原始对象的结果,以避免重复计算或访问资源。
- **要点5:**5、异常代理:通常我们的系统中如果有统一的异常机制或者ERROR_CODE的机制,可以通过创建一个统一的代理来做处理。
**记忆锚点:**Spring → 在代理对象 → 远程代理 → 动态代理 → AOP → 对象来控制对其他对象
关键取舍:
- 3、缓存代理:缓存代理可以缓存原始对象的结果,以避免重复计算或访问资源。
易错提醒:
- 3、缓存代理:缓存代理可以缓存原始对象的结果,以避免重复计算或访问资源。
加分表达:
- 他的常用场景有以下几个: 1、远程代理:在分布式系统中,代理模式可用于代理远程对象。
- 先访问代理对象,代理对象会去查询缓存,如果缓存中你没有,再去查询真实对象。
- 5、异常代理:通常我们的系统中如果有统一的异常机制或者ERROR_CODE的机制,可以通过创建一个统一的代理来做处理。
追问准备:
- 围绕「Spring」:底层原理是什么?使用时有哪些边界和常见坑?
- 围绕「在代理对象」:底层原理是什么?使用时有哪些边界和常见坑?
- 围绕「远程代理」:底层原理是什么?使用时有哪些边界和常见坑?
- 如果线上出现异常,你会如何定位、验证并规避?
典型回答
代理模式是一种结构设计模式,它允许通过创建代理对象来控制对其他对象的访问。代理对象充当原始对象的接口,客户端通过代理对象间接地访问原始对象,并可以在访问过程中添加额外的逻辑或控制。
代理模式的主要目的是通过引入代理对象,为原始对象提供一层间接访问的方式,以实现对原始对象的控制、保护或增强。他的常用场景有以下几个:
1、远程代理:在分布式系统中,代理模式可用于代理远程对象。远程代理隐藏了远程对象的实际实现细节,使客户端可以像访问本地对象一样访问远程对象。如Dubbo的实现就是用到了代理模式。
打开文档:✅Dubbo如何实现像本地方法一样调用远程方法的?
2、动态代理:动态代理允许在运行时动态地创建代理对象,并动态地将方法调用分派到不同的处理器。它通过Java的反射机制实现,可以用于实现通用的代理逻辑,而无需为每个被代理的类单独创建代理。如Spring的AOP,就用到了动态代理。
3、缓存代理:缓存代理可以缓存原始对象的结果,以避免重复计算或访问资源。一般我们在用到缓存的时候,可以用这种模式。先访问代理对象,代理对象会去查询缓存,如果缓存中你没有,再去查询真实对象。
4、日志代理:这种用的也挺多的,当我需要做日志记录的时候,可以做一个代理,在代理对象中进行统一的日志记录及管理。
5、异常代理:通常我们的系统中如果有统一的异常机制或者ERROR_CODE的机制,可以通过创建一个统一的代理来做处理。在代理对象中这些异常的捕捉及转换。
扩展知识
示例
假设我们有一个比较耗时的查询服务,他的接口定义及实现如下:
java
/**
* @Author Hollis
**/
public interface DataService {
String getData();
}java
/**
* @Author Hollis
**/
public class DataServiceImpl implements DataService {
@Override
public String getData() {
//执行非常耗时的数据查询
return "Data from expensive operation";
}
}这时候我们想要引入缓存,则可以定义以一个代理:
java
public class CachedDataServiceProxy implements DataService {
private DataService dataService;
@Autowired
private CacheService cacheService;
public CachedDataServiceProxy(DataService dataService) {
this.dataService = dataService;
}
@Override
public String getData() {
//先从缓存中获取
String cachedData = cacheService.getdata();
//缓存中没有,则查询接口
if (cachedData == null) {
data = dataService.getData();
//获取到以后再保存到缓存中
cacheService.putData(data);
}
return cachedData;
}
}写一个测试如下:
java
public static void main(String[] args) {
DataService dataService = new DataServiceImpl();
DataService cachedDataService = new CachedDataServiceProxy(dataService);
cachedDataService.getData();
}以上,就是一个代理模式的具体实现了,一般来说,我们也会基于上面的思想,再结合Spring的AOP的机制,和自定义注解,实现一个简单的注解,可以把他加到方法上就能实现缓存的逻辑了。