【二十四讲】ControllerAdvice 之 @InitBinder
- 绑定器工厂的扩展点:@InitBinder 及来源
- 编程技巧:缓存加速
InitBinder
三类
@InitBinder
@ExceptionHandler
@ModelAttribute
@InitBinder 的来源有两个
1. @ControllerAdvice 中 @InitBinder 标注的方法,由 RequestMappingHandlerAdapter 在初始化时解析并记录
2. Controller 中 @InitBinder 标注的方法,由 RequestMappingHandlerAdapter 会在控制器方法首次执行时解析并记录
log.debug("1. 刚开始...");
showBindMethods(handlerAdapter);
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-WgW8Fgkx-1665585508602)(Spring-24.assets/image-20220913225059040.png)]
全局的 InitiBinder 初始化了,控制器中 还未初始化
模拟调用Controller1 的 foo
Method getDataBinderFactory = RequestMappingHandlerAdapter.class.getDeclaredMethod("getDataBinderFactory", HandlerMethod.class);
getDataBinderFactory.setAccessible(true);
log.debug("2. 模拟调用 Controller1 的 foo 方法时 ...");
getDataBinderFactory.invoke(handlerAdapter, new HandlerMethod(new WebConfig.Controller1(), WebConfig.Controller1.class.getMethod("foo")));
showBindMethods(handlerAdapter);
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-MgsRyUji-1665585508603)(Spring-24.assets/image-20220913225434234.png)]
模拟调用 Controller2 的 bar 方法
log.debug("3. 模拟调用 Controller2 的 bar 方法时 ...");
getDataBinderFactory.invoke(handlerAdapter, new HandlerMethod(new WebConfig.Controller2(), WebConfig.Controller2.class.getMethod("bar")));
showBindMethods(handlerAdapter);
学到了什么
a. Method 对象的获取利用了缓存来进行加速
b. 绑定器工厂的扩展点(advice 之一), 通过 @InitBinder 扩展类型转换器
控制器方法执行流程-initBinder
准备 @InitBinder 在整个 HandlerAdapter 调用过程中所处的位置
- RequestMappingHandlerAdapter 在图中缩写为 HandlerAdapter
- HandlerMethodArgumentResolverComposite 在图中缩写为 ArgumentResolvers
- HandlerMethodReturnValueHandlerComposite 在图中缩写为 ReturnValueHandlers
总结
- RequestMappingHandlerAdapter 初始化时会解析 @ControllerAdvice 中的 @InitBinder 方法
- RequestMappingHandlerAdapter 会以类为单位,在该类首次使用时,解析此类的 @InitBinder 方法
- 以上两种 @InitBinder 的解析结果都会缓存来避免重复解析
- 控制器方法调用时,会综合利用本类的 @InitBinder 方法和 @ControllerAdvice 中的 @InitBinder 方法创建绑定工厂