描述
- 结构型设计模式
- 统一规范
- 它主要是为了解决已经存在的类不符合我们的要求,从而使用适配器让不兼容的类能够在一起工作
案例
SpringMVC中的HandlerAdapter
-
DispatcherServlet
收到请求后,先从HandlerMapping
中获取可以处理该请求的handler
,而handler有多种类型 -
HandlerMethod、HandlerFunction、HttpRequestHandler等这些Handler并没有统一的规范(类型不一样,没有实现统一的接口或继承统一的类,处理请求的方法也不同)。在
DispatcherServlet
中如果直接与这些Hanlder交互,调用方式是不确定的,将会产生大量if-else分支,扩展增加Handler时还需要修改代码,这也违反了开闭原则。 -
采用适配器模式,定义一个接口
HandlerAdapter
作为统一规范,然后为每个handler创建一个适配器,所有的适配器都实现该接口,在每个适配器内部触发对应的Handler的方法,这样DispatcherServlet
只需要和拥有统一规范的适配器交互即可 -
适配器将不同类型的处理器适配到
DispathcherServlet
的处理流程中。org.springframework.web.servlet.DispatcherServlet#doDispatch
如RequestMappingHandlerAdapter
适配器,实现了HandlerAdapter
接口,用于处理HandlerMethod
这个handler(HandlerMethod对应的是@Controller+@RequestMapping标注的方法)
spring aop中的MethodInterceptor
spring aop
使用advice
增强被代理类的方法,而advice有多种类型:AspectJMethodBeforeAdvice
、AspectJAfterAdvice
、AspectJAfterReturningAdvice
、AspectJAfterThrowingAdvice
、AspectJAroundAdvice
- 这些advice并没有一个统一的触发方法,例如
AspectJMethodBeforeAdvice
的触发方法是before,AspectJAfterReturningAdvice
的触发方法是afterReturning - spring aop触发增强方法的入口是
ReflectiveMethodInvocation
类,如果该类直接与各个advice交互,就要处理不同方法的调用。使用适配器对ReflectiveMethodInvocation
类屏蔽不同advice触发方式的差异,避免ReflectiveMethodInvocation
中存在过多的逻辑 - 如上图,前三个advice都是
MethodInterceptor
的实现类,因此不需要额外为它们增加适配器,而后两个advice则不同
- 以
AspectJMethodBeforeAdvice
为例,适配器MethodBeforeAdviceInterceptor
持有被适配者AspectJMethodBeforeAdvice
的引用,适配器接收到请求后将,将请求再转发给被适配者
openfeign对响应解码
org.springframework.cloud.openfeign.support.SpringDecoder#decode
--> org.springframework.web.client.HttpMessageConverterExtractor#extractData
从不同的响应中抽取数据。由于extractData方法要求的类型是ClientHttpResponse
,而feign.Response
并不符合,使用适配器FeignResponseAdapter
可让extractData方法从feign.Response
中抽取数据