doDispatch 源码实现如下:
protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {HttpServletRequest processedRequest = request;HandlerExecutionChAIn mappedHandler = null;boolean multipartRequestParsed = false;WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);try {try {ModelAndView mv = null;Object dispatchException = null;try {processedRequest = this.checkMultipart(request);multipartRequestParsed = processedRequest != request;mappedHandler = this.getHandler(processedRequest);if (mappedHandler == null) {this.noHandlerFound(processedRequest, response);return;}HandlerAdapter ha = this.getHandlerAdapter(mappedHandler.getHandler());String method = request.getMethod();boolean isGet = HttpMethod.GET.matches(method);if (isGet || HttpMethod.HEAD.matches(method)) {long lastModified = ha.getLastModified(request, mappedHandler.getHandler());if ((new ServletWebRequest(request, response)).checkNotModified(lastModified) && isGet) {return;}}// 调用预处理【重点】if (!mappedHandler.applyPreHandle(processedRequest, response)) {return;}// 执行 Controller 中的业务mv = ha.handle(processedRequest, response, mappedHandler.getHandler());if (asyncManager.isConcurrentHandlingStarted()) {return;}this.applyDefaultViewName(processedRequest, mv);mappedHandler.applyPostHandle(processedRequest, response, mv);} catch (Exception var20) {dispatchException = var20;} catch (Throwable var21) {dispatchException = new NestedServletException("Handler dispatch failed", var21);}this.processDispatchResult(processedRequest, response, mappedHandler, mv, (Exception)dispatchException);} catch (Exception var22) {this.triggerAfterCompletion(processedRequest, response, mappedHandler, var22);} catch (Throwable var23) {this.triggerAfterCompletion(processedRequest, response, mappedHandler, new NestedServletException("Handler processing failed", var23));}} finally {if (asyncManager.isConcurrentHandlingStarted()) {if (mappedHandler != null) {mappedHandler.applyAfterConcurrentHandlingStarted(processedRequest, response);}} else if (multipartRequestParsed) {this.cleanupMultipart(processedRequest);}}}
从上述源码可以看出在开始执行 Controller 之前,会先调用 预处理方法 applyPreHandle , 而 applyPreHandle 方法的实现源码如下:
boolean applyPreHandle(HttpServletRequest request, HttpServletResponse response) throws Exception {for(int i = 0; i < this.interceptorList.size(); this.interceptorIndex = i++) {// 获取项目中使用的拦截器 HandlerInterceptorHandlerInterceptor interceptor = (HandlerInterceptor)this.interceptorList.get(i);if (!interceptor.preHandle(request, response, this.handler)) {this.triggerAfterCompletion(request, response, (Exception)null);return false;}}return true;}
从上述源码可以看出,在 applyPreHandle 中会获取所有的拦截器 HandlerInterceptor 并执行拦截器中的 preHandle 方法,这样就会咱们前面定义的拦截器对应上了,如下图所示:
文章插图
【SpringBoot拦截器和动态代理有什么区别?】此时用户登录权限的验证方法就会执行,这就是拦截器的执行过程 。因此,可以得出结论 , 拦截器的实现主要是依赖 Servlet 或 Spring 执行流程来进行拦截和功能增强的 。
2、动态代理动态代理是一种设计模式,它是指在运行时提供代理对象 , 来扩展目标对象的功能 。在 Spring 中的,动态代理的实现手段有以下两种:
- JDK 动态代理:通过反射机制生成代理对象,目标对象必须实现接口 。
- CGLIB 动态代理:通过生成目标类的子类来实现代理,不要求目标对象实现接口 。
- 扩展目标对象的功能:如添加日志、验证参数等 。
- 控制目标对象的访问:如进行权限控制 。
- 延迟加载目标对象:在需要时才实例化目标对象 。
- 远程代理:将请求转发到远程的目标对象上 。
“3、拦截器 VS 动态代理因此 , 我们可以得出结论,拦截器和动态代理虽然都是用来实现功能增强的,但二者完全不同,他们的主要区别体现在以下几点:
JDK 动态代理和 CGLIB 的区别详见:www.javacn.site/interview/spring/jdk_cglib.html
”
- 使用范围不同:拦截器通常用于 Spring MVC 中,主要用于拦截 Controller 请求 。动态代理可以使用在 Bean 中,主要用于提供 bean 的代理对象 , 实现对 bean 方法的拦截 。
推荐阅读
- 机器学习如何帮助企业应对网络威胁?
- 热水器只有冷水没热水怎么办
- 低碳产品包括 低碳产品包括A越野车B新能源汽车C白炽灯D太阳能热水器
- 笔记本电源怎么拆开 电源适配器拆开方法图解
- 热水器一冷一热怎么解决 热水器一冷一热怎么解决视频
- 万和热水器使用方法 万和热水器使用方法视频万和燃气热水器怎么使用
- 男生的生殖长一般多大 男人的生殖器多长多大才标准
- 男生器官上长了痘痘是因为什么 男生器官上长痘痘的原因
- 路由器放在冰箱上是否影响网速 路由器可以放在冰箱上吗
- 扩音器录音使用方法图解 扩音器录音使用方法