HandlerMethodReturnValueHandler与适配器模式使用
书接上文SpringBoot统一修改API返回值的两种方式中自定义HandlerMethodReturnValueHandler的内容,最后说道getDefaultReturnValueHandlers方法中添加了很多处理返回值的处理器,那这些处理器是如何生效的呢?
HandlerMethodReturnValueHandler在处理返回值时时如何使用适配器模式
通过分析DispatchServelet的doDispatch方法中的内容可以机进行追溯,
主要就行进行了各种适配器的选择
HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());
可以看到HandlerAdapter中的具体实现类中与我们比较相关的还是AbstractHandlerMethodAdapter,但是进一步可以发现RequestMappingHandlerAdapter是继承自AbstractHandlerMethodAdapter且实现了相应功能
那最后是如何选择到我们的自定义HandlerMethodReturnValueHandler的内容的呢
DispatchServelet中获取到了HandlerAdapter 之后即开始执行hanle方法
通过追踪handle方法到RequestMappingHandlerAdapter#invokeHandlerMethod
继而追踪到
@Override
public void handleReturnValue(@Nullable Object returnValue, MethodParameter returnType,
ModelAndViewContainer mavContainer, NativeWebRequest webRequest) throws Exception {
HandlerMethodReturnValueHandler handler = selectHandler(returnValue, returnType);
if (handler == null) {
throw new IllegalArgumentException("Unknown return value type: " + returnType.getParameterType().getName());
}
handler.handleReturnValue(returnValue, returnType, mavContainer, webRequest);
}
最后通过适配器模式选择了排在第一个的我们的自定义的HandlerMethodReturnValueHandler的方法
选择适配器的方法即为通用的适配器模式实现方式,
@Nullable
private HandlerMethodReturnValueHandler selectHandler(@Nullable Object value, MethodParameter returnType) {
boolean isAsyncValue = isAsyncReturnValue(value, returnType);
for (HandlerMethodReturnValueHandler handler : this.returnValueHandlers) {
if (isAsyncValue && !(handler instanceof AsyncHandlerMethodReturnValueHandler)) {
continue;
}
if (handler.supportsReturnType(returnType)) {
return handler;
}
}
return null;
}
通过将this.returnValueHandlers的第一个设置为自定义方法,即选中我们自定义的方法后就直接返回,不再进行后续方法的选择。
适配器模式
在Spring中还有很多其他使用适配器的地方,通过这种方法能够较好的选择合适的处理方法,也能够方便我们进行自定义扩展
当我看到适配器模式时,我自然而然的想到了策略模式,那么适配器模式和策略模式简化if判断到底有什么不同呢?
从我个人的理解而言,策略模式首先需要去判断你属于某个策略,然后去执行相应的操作。而适配器模式则是内部判断你是否能够适配当前操作,然后再去执行
从更加规范的角度理解
策略模式中 Context 是要接收 Strategy 类,而所有的策略也是需要实现 Strategy 类,大家都需要共同遵守 Strategy 类的约定。
适配器模式模式中 MediaAdapter 没有这层约定,第三方的 AdvancedMediaPlayer 压根就不管你那些什么约定,只管自己的输出。MediaAdapter 对接完 AdvancedMediaPlayer 后输出统一的接口让外部访问即可。
相关文章
- ctf近期总结
- php处理时间戳解决时间戳中月份、日期前带不带0的问题
- 迄今为止把同步/异步/阻塞/非阻塞/BIO/NIO/AIO讲的这么清楚的好文章
- 为啥程序会有bug?
- PHP实现WebSocket实例详解
- 轮询以及webSocket与socket.io原理
- 开发Chrome插件,实现网站自动登录
- PHP curl或file_get_contents下载图片损坏或无法打开
- HBuilderX连接(安卓)逍遥模拟器【简洁】(亲测可行)
- 小程序-扩展能力图片上传Uploader组件
- Windows Hexo博客安装配置优化(小白篇)
- 什么是Azure Network Watcher
- 微信小程序反编译解包教程
- phpstorm如何修改php版本
- PHPstorm设置字体大小
- PhpStorm 2018中文破解版附安装破解教程
- ps安装蓝湖插件教程
- 针对宝塔面板一个站点多个域名使用SSL证书的解决方案
- Web for pentester_writeup
- centos7安装ImageMagick