Spring源码学习笔记
Posted DarkFuture
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Spring源码学习笔记相关的知识,希望对你有一定的参考价值。
Spring源码学习笔记(三)
前言----
最近花了些时间看了《Spring源码深度解析》这本书,算是入门了Spring的源码吧。打算写下系列文章,回忆一下书的内容,总结代码的运行流程。推荐那些和我一样没接触过SSH框架源码又想学习的,阅读郝佳编著的《Spring源码深度解析》这本书,会是个很好的入门。
DispatcherServlet 实现核心功能
和普通的 Servelt 类一样, DispatcherServlet 中的 doGet() 和 doPost() 方法是实现其核心逻辑的方法, 在其父类 FrameworkServlet 中有该函数的实现。
1 protected final void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { 2 this.processRequest(request, response); 3 } 4 5 protected final void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { 6 this.processRequest(request, response); 7 }
实现逻辑全部交给 processRequest() 方法, 继续跟踪~~~~
1 protected final void processRequest(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { 2 //第一步: 记录时间 3 long startTime = System.currentTimeMillis(); 4 Throwable failureCause = null; 5 //第二步: 记录当前线程的 LocaleContext 以及 RequestAttributes 6 LocaleContext previousLocaleContext = LocaleContextHolder.getLocaleContext(); 7 //第三步: 根据当前的 request 生成 LocaleContext 和 RequestAttributes 8 LocaleContext localeContext = this.buildLocaleContext(request); 9 RequestAttributes previousAttributes = RequestContextHolder.getRequestAttributes(); 10 ServletRequestAttributes requestAttributes = this.buildRequestAttributes(request, response, previousAttributes); 11 WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request); 12 asyncManager.registerCallableInterceptor(FrameworkServlet.class.getName(), new FrameworkServlet.RequestBindingInterceptor(null)); 13 this.initContextHolders(request, localeContext, requestAttributes); 14 15 try { 16 //第四步: 核心 doService() 方法 17 this.doService(request, response); 18 } catch (ServletException var17) { 19 failureCause = var17; 20 throw var17; 21 } finally { 22 //第五步: 恢复 LocaleContext 以及 RequestAttributes 23 this.resetContextHolders(request, previousLocaleContext, previousAttributes); 24 if(requestAttributes != null) { 25 requestAttributes.requestCompleted(); 26 } 27 //第六步: 无论成功失败, 发布事件 28 this.publishRequestHandledEvent(request, startTime, (Throwable)failureCause); 29 } 30 31 }
在 processRequest() 方法中, 操作了 LocaleContext 和 RequestAttributes 外, 并没做什么, 核心逻辑在 doService() 方法中。 欲知后事, 烧香倒酒~~·
1 protected void doService(HttpServletRequest request, HttpServletResponse response) throws Exception { 2 3 Map<String, Object> attributesSnapshot = null; 4 if(WebUtils.isIncludeRequest(request)) { 5 this.logger.debug("Taking snapshot of request attributes before include"); 6 attributesSnapshot = new HashMap(); 7 //第一步: 生成迭代器,为当前的 request 的属性做快照 8 Enumeration attrNames = request.getAttributeNames(); 9 10 label113: 11 while(true) { 12 String attrName; 13 do { 14 if(!attrNames.hasMoreElements()) { 15 break label113; 16 } 17 18 attrName = (String)attrNames.nextElement(); 19 } while(!this.cleanupAfterInclude && !attrName.startsWith("org.springframework.web.servlet")); 20 21 attributesSnapshot.put(attrName, request.getAttribute(attrName)); 22 } 23 } 24 25 //第二步: 给当前 Request 设置 已获取到的属性 request.setAttribute(WEB_APPLICATION_CONTEXT_ATTRIBUTE, this.getWebApplicationContext()); 26 request.setAttribute(LOCALE_RESOLVER_ATTRIBUTE, this.localeResolver); 27 request.setAttribute(THEME_RESOLVER_ATTRIBUTE, this.themeResolver); 28 request.setAttribute(THEME_SOURCE_ATTRIBUTE, this.getThemeSource()); 29 FlashMap inputFlashMap = this.flashMapManager.retrieveAndUpdate(request, response); 30 if(inputFlashMap != null) { 31 request.setAttribute(INPUT_FLASH_MAP_ATTRIBUTE, Collections.unmodifiableMap(inputFlashMap)); 32 } 33 34 request.setAttribute(OUTPUT_FLASH_MAP_ATTRIBUTE, new FlashMap()); 35 request.setAttribute(FLASH_MAP_MANAGER_ATTRIBUTE, this.flashMapManager); 36 37 try { 38 //第三步: 准备工作后的真正逻辑处理 39 this.doDispatch(request, response); 40 } finally { 41 if(WebAsyncUtils.getAsyncManager(request).isConcurrentHandlingStarted()) { 42 return; 43 } 44 //第四步: 从快照当中恢复属性 45 if(attributesSnapshot != null) { 46 this.restoreAttributesAfterInclude(request, attributesSnapshot); 47 } 48 49 } 50 51 }
一步一步似爪牙, 是魔鬼的步伐, 是。。。。。 这个 doDispatch() 方法真正进入了核心 <( ̄︶ ̄)↗[GO!]
1 protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception { 2 HttpServletRequest processedRequest = request; 3 HandlerExecutionChain mappedHandler = null; 4 boolean multipartRequestParsed = false; 5 WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request); 6 7 try { 8 try { 9 ModelAndView mv = null; 10 Exception dispatchException = null; 11 12 try { 13 //第一步: 检测 MultipartContent 类型的 request 14 processedRequest = this.checkMultipart(request); 15 multipartRequestParsed = processedRequest != request; 16 //第二步: 根据当前的 request 获取对应的 handler 17 mappedHandler = this.getHandler(processedRequest); 18 if(mappedHandler == null || mappedHandler.getHandler() == null) { 19 //第三步: 没有 对应的 handler 则报异常 20 this.noHandlerFound(processedRequest, response); 21 return; 22 } 23 //第四步: 根据 handler 获取对应的 handlerAdapter 24 HandlerAdapter ha = this.getHandlerAdapter(mappedHandler.getHandler()); 25 //第五步: 这里是对 http 的Last-Modified 头的处理, 相当于缓存策略 26 String method = request.getMethod(); 27 boolean isGet = "GET".equals(method); 28 if(isGet || "HEAD".equals(method)) { 29 long lastModified = ha.getLastModified(request, mappedHandler.getHandler()); 30 if(this.logger.isDebugEnabled()) { 31 String requestUri = urlPathHelper.getRequestUri(request); 32 this.logger.debug("Last-Modified value for [" + requestUri + "] is: " + lastModified); 33 } 34 35 if((new ServletWebRequest(request, response)).checkNotModified(lastModified) && isGet) { 36 return; 37 } 38 } 39 //第六步: 调用拦截器的 preHandler 方法 40 if(!mappedHandler.applyPreHandle(processedRequest, response)) { 41 return; 42 } 43 44 try { 45 //第七步: 调用 HandlerAdapter 的方法, 返回视图 46 mv = ha.handle(processedRequest, response, mappedHandler.getHandler()); 47 } finally { 48 if(asyncManager.isConcurrentHandlingStarted()) { 49 return; 50 } 51 52 } 53 54 this.applyDefaultViewName(request, mv); 55 //第八步: 调用拦截器的 postHandler 方法 56 mappedHandler.applyPostHandle(processedRequest, response, mv); 57 } catch (Exception var28) { 58 dispatchException = var28; 59 } 60 //第九步: 进行返回视图的跳转 以及 激活触发器 61 this.processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException); 62 } catch (Exception var29) { 63 this.triggerAfterCompletion(processedRequest, response, mappedHandler, var29); 64 } catch (Error var30) { 65 this.triggerAfterCompletionWithError(processedRequest, response, mappedHandler, var30); 66 } 67 68 } finally { 69 if(asyncManager.isConcurrentHandlingStarted()) { 70 mappedHandler.applyAfterConcurrentHandlingStarted(processedRequest, response); 71 return; 72 } else { 73 if(multipartRequestParsed) { 74 this.cleanupMultipart(processedRequest); 75 } 76 77 } 78 } 79 }
复杂的逻辑, 分成一个个步骤, 接下来详解 doDispatch() 方法的每个步骤。 另开新篇~~~~ ( ﹁ ﹁ ) ~→
doDispatch( HttpServletRequest request, HttpServletResponse response )
一, 检测 MutipartContent 类型的 request
1 protected HttpServletRequest checkMultipart(HttpServletRequest request) throws MultipartException { 2 //第一步: 判断类型 3 if(this.multipartResolver != null && this.multipartResolver.isMultipart(request)) { 4 if(!(request instanceof MultipartHttpServletRequest)) { 5 //第二步: 调用方法 6 return this.multipartResolver.resolveMultipart(request); 7 } 8 9 this.logger.debug("Request is already a MultipartHttpServletRequest - if not in a forward, this typically results from an additional MultipartFilter in web.xml"); 10 } 11 //第三步: 直接返回 12 return request; 13 }
二, 根据 Request 获取 Handler
1 protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception { 2 //第一步: 遍历所有的 HandlerMapping 3 Iterator var2 = this.handlerMappings.iterator(); 4 5 HandlerExecutionChain handler; 6 do { 7 if(!var2.hasNext()) { 8 return null; 9 } 10 11 HandlerMapping hm = (HandlerMapping)var2.next(); 12 if(this.logger.isTraceEnabled()) { 13 this.logger.trace("Testing handler map [" + hm + "] in DispatcherServlet with name \'" + this.getServletName() + "\'"); 14 } 15 //第二步: 调用 HandlerMapping 的方法 16 handler = hm.getHandler(request); 17 } while(handler == null); 18 19 return handler; 20 }
在 getHandler() 方法中, 第二步调用 HandlerMapping 的 getHandler() 方法, 其实现是在父类 AbstractHandlerMapping 中
AbstractHandlerMapping 的 getHandler() 实现 :
1 public final HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception { 2 //第一步: 根据 request 获取对应的 handler 3 Object handler = this.getHandlerInternal(request); 4 if(handler == null) { 5 //第二步: 使用默认的 handler 6 handler = this.getDefaultHandler(); 7 } 8 9 if(handler == null) { 10 return null; 11 } else { 12 if(handler instanceof String) { 13 //第三步: 若为 String 类型, 实例化它 14 String handlerName = (String)handler; 15 handler = this.getApplicationContext().getBean(handlerName); 16 } 17 //第四步: 封装类型 18 return this.getHandlerExecutionChain(handler, request); 19 } 20 }
getHandler() 第一步中的 getHandlerInternal() 方法, 其实现是在 AbstractUrlHandlerMapping 类中:
1 protected Object getHandlerInternal(HttpServletRequest request) throws Exception { 2 //第一步: 截取 url 的有效路径 3 String lookupPath = this.getUrlPathHelper().getLookupPathForRequest(request); 4 //第二步: 根据路径获取 handler 5 Object handler = this.lookupHandler(lookupPath, request); 6 if(handler == null) { 7 Object rawHandler = null; 8 //第三步: 路径为 “/” 的情况 9 if("/".equals(lookupPath)) { 10 rawHandler = this.getRootHandler(); 11 } 12 //第四步: 路径为 null 的情况, 使用默认 handler 13 if(rawHandler == null) { 14 rawHandler = this.getDefaultHandler(); 15 } 16 17 if(rawHandler != null) { 18 if(rawHandler instanceof String) { 19 //第五步: 根据 name 获取对应的 bean 20 String handlerName = (String)rawHandler; 21 rawHandler = this.getApplicationContext().getBean(handlerName); 22 } 23 //第六步: 模板方法 (往后看) 24 this.validateHandler(rawHandler, request); 25 handler = this.buildPathExposingHandler(rawHandler, lookupPath, lookupPath, (Map)null); 26 } 27 } 28 29 return handler; 30 }
绝望的感觉, 对方不想和你说话,并又双叒叕向你扔了一大堆代码。。。 (ノಠ益ಠ)ノ彡┻━┻
在 getHandlerInternal() 方法中, 第二步 lookupHandler() 的实现:
1 protected Object lookupHandler(String urlPath, HttpServletRequest request) throws Exception { 2 Object handler = this.handlerMap.get(urlPath); 3 //第一步: 缓存 handlerMap 中存在的情况 4 if(handler != null) { 5 if(handler instanceof String) { 6 String handlerName = (String)handler; 7 handler = this.getApplicationContext().getBean(handlerName); 8 } 9 10 this.validateHandler(handler, request); 11 return this.buildPathExposingHandler(handler, urlPath, urlPath, (Map)null); 12 } else { 13 //第二步: 同配符匹配的情况 14 List<String> matchingPatterns = new ArrayList(); 15 Iterator var5 = this.handlerMap.keySet().iterator(); 16 17 while(var5.hasNext()) { 18 String registeredPattern = (String)var5.next(); 19 //第三步: 添加所有的要匹配的 Handler 20 if(this.getPathMatcher().match(registeredPattern, urlPath)) { 21 matchingPatterns.add(registeredPattern); 22 } 23 } 24 25 String bestPatternMatch = null; 26 Comparator<String> patternComparator = this.getPathMatcher().getPatternComparator(urlPath); 27 if(!matchingPatterns.isEmpty()) { 28 //第四步: 根据 Comparator 排序所有的 Handler 29 Collections.sort(matchingPatterns, patternComparator); 30 if(this.logger.isDebugEnabled()) { 31 this.logger.debug("Matching patterns for request [" + urlPath + "] are " + matchingPatterns); 32 } 33 //第五步: 获取匹配的 Handler 34 bestPatternMatch = (String)matchingPatterns.get(0); 35 } 36 37 if(bestPatternMatch != null) { 38 handler = this.handlerMap.get(bestPatternMatch); 39 String pathWithinMapping; 40 //第六步: 若是 String 类型, 则实例化 41 if(handler instanceof String) { 42 pathWithinMapping = (String)handler; 43 handler = this.getApplicationContext().getBean(pathWithinMapping); 44 } 45 46 this.validateHandler(handler, request); 47 pathWithinMapping = this.getPathMatcher().extractPathWithinPattern(bestPatternMatch, urlPath); 48 //第七步: 若存在多个 最佳匹配, 在这些匹配中选出正确的 URI template variables 49 Map<String, String> uriTemplateVariables = new LinkedHashMap(); 50 Iterator var9 = matchingPatterns.iterator(); 51 52 while(var9.hasNext()) { 53 String matchingPattern = (String)var9.next(); 54 if(patternComparator.compare(bestPatternMatch, matchingPattern) == 0) { 55 Map<String, String> vars = this.getPathMatcher().extractUriTemplateVariables(matchingPattern, urlPath); 56 Map<String, String> decodedVars = this.getUrlPathHelper().decodePathVariables(request, vars); 57 uriTemplateVariables.putAll(decodedVars); 58 } 59 } 60 //第八步: 封装 61 return this.buildPathExposingHandler(handler, bestPatternMatch, pathWithinMapping, uriTemplateVariables); 62 } else { 63 return null; 64 } 65 } 66 }
其实在 lookupHandler() 方法当中, 只是一个 if-else 语句判断了 是直接匹配的情况 还是 同配符匹配的情况,最后把获取的 handler 封装成 HandlerExecutionChain 类。
1 protected Object buildPathExposingHandler(Object rawHandler, String bestMatchingPattern, String pathWithinMapping, Map<String, String> uriTemplateVariables) { 2 //第一步: 封装成 HandlerExecutionChain 类型 3 HandlerExecutionChain chain = new HandlerExecutionChain(rawHandler); 4 //第二步: 为 chain 添加两个拦截器 5 chain.addInterceptor(new AbstractUrlHandlerMapping.PathExposingHandlerInterceptor(bestMatchingPattern, pathWithinMapping)); 6 if(!CollectionUtils.isEmpty(uriTemplateVariables)) { 7 chain.addInterceptor(new AbstractUrlHandlerMapping.UriTemplateVariablesHandlerInterceptor(uriTemplateVariables)); 8 } 9 10 return chain; 11 }
在 getHandler() 方法中,第四步封装类型 getHandlerExecutionChain() 方法的实现:
1 protected HandlerExecutionChain getHandlerExecutionChain(Object handler, HttpServletRequest request) { 2 HandlerExecutionChain chain = handler instanceof HandlerExecutionChain?(HandlerExecutionChain)handler:new HandlerExecutionChain(handler); 3 chain.addInterceptors(this.getAdaptedInterceptors()); 4 String lookupPath = this.urlPathHelper.getLookupPathForRequest(request); 5 Iterator var5 = this.mappedInterceptors.iterator(); 6 //第一步: 封装过程, 就是为 chain 添加拦截器 7 while(var5.hasNext()) { 8 MappedInterceptor mappedInterceptor = (MappedInterceptor)var5.next(); 9 if(mappedInterceptor.matches(lookupPath, this.pathMatcher)) { 10 chain.addInterceptor(mappe以上是关于Spring源码学习笔记的主要内容,如果未能解决你的问题,请参考以下文章
初识Spring源码 -- doResolveDependency | findAutowireCandidates | @Order@Priority调用排序 | @Autowired注入(代码片段