外观
一句话答案
将一个类的接口转换为客户端期望的接口,使不兼容的类协作;Spring HandlerAdapter 适配不同类型 Controller。
核心要点
适配器模式将一个类的接口转换成客户期望的另一个接口,使原本接口不兼容的类可以一起工作。
两种实现方式:
| 方式 | 实现 | 特点 |
|---|---|---|
| 类适配器 | 适配器继承被适配类 + 实现目标接口 | Java 单继承限制,不常用 |
| 对象适配器 | 适配器持有被适配对象的引用 + 实现目标接口 | 推荐,组合优于继承 |
java
// 目标接口
public interface Target {
void request();
}
// 被适配的类(旧接口)
public class Adaptee {
public void specificRequest() { /* 旧逻辑 */ }
}
// 对象适配器
public class Adapter implements Target {
private Adaptee adaptee;
public Adapter(Adaptee adaptee) {
this.adaptee = adaptee;
}
@Override
public void request() {
adaptee.specificRequest(); // 转发调用
}
}Spring MVC 中的 HandlerAdapter:
Spring MVC 支持多种类型的 Controller:
@Controller+@RequestMapping(注解式)- 实现
Controller接口 - 实现
HttpRequestHandler接口
这些 Handler 的调用方式各不相同。HandlerAdapter 作为适配器,将不同类型 Handler 的调用方式统一:
DispatcherServlet
│
▼ 调用统一接口 adapter.handle(request, response, handler)
HandlerAdapter(目标接口)
├── RequestMappingHandlerAdapter → 处理 @RequestMapping 注解的方法
├── SimpleControllerHandlerAdapter → 处理实现 Controller 接口的类
└── HttpRequestHandlerAdapter → 处理实现 HttpRequestHandler 的类核心流程:
DispatcherServlet根据请求找到 Handler(Controller 方法)- 遍历所有
HandlerAdapter,找到能处理该 Handler 的适配器(supports(handler)返回 true) - 调用适配器的
handle()方法,内部将请求转发给对应的 Handler
Java SDK 中的适配器:
Arrays.asList()—— 数组适配为 ListInputStreamReader—— 字节流适配为字符流Collections.enumeration()—— Collection 适配为 Enumeration
追问与易错
追问方向:
- 类适配器和对象适配器区别?
- Spring MVC 为什么需要 HandlerAdapter?
- 和门面区别?
易错点:
- ❌ 适配器就是封装——核心是接口转换
- ❌ 不推荐用——遗留系统集成非常有用
💡 记忆锚点
万能充电转接头:你的三脚插头(旧接口)插不进两孔插座(目标接口),转接头(Adapter)两边各适配一个口。Spring MVC的HandlerAdapter就是这个转接头——把注解式/@Controller/HttpRequestHandler三种不同插头统一转成DispatcherServlet认识的两孔插座。