说明:本文只对 HandlerMethod 的获取进行分析,不对mvc的执行流程分析,所有的一起源码都是针对常见的请求(@Controller 和 @RequestMapping)
上面已经知道了最后执行的是HandlerExecutionChain.handler,那就看看这个属性是如何被赋值的
方法入口为DispatcherServlet.doDispatch.getHandler()
protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception { HttpServletRequest processedRequest = request; HandlerExecutionChain mappedHandler = null; boolean multipartRequestParsed = false; WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request); try { ModelAndView mv = null; Exception dispatchException = null; try { processedRequest = checkMultipart(request); multipartRequestParsed = (processedRequest != request); // Determine handler for the current request. //就是在这个地方获取的 handlerExecutionChain,也是在这里获取的 handlerMethod mappedHandler = getHandler(processedRequest); if (mappedHandler == null) { noHandlerFound(processedRequest, response); return; } // Determine handler adapter for the current request. //获取适配器 HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler()); // Process last-modified header, if supported by the handler. String method = request.getMethod(); boolean isGet = "GET".equals(method); if (isGet || "HEAD".equals(method)) { long lastModified = ha.getLastModified(request, mappedHandler.getHandler()); if (new ServletWebRequest(request, response).checkNotModified(lastModified) && isGet) { return; } } // 拦截器的执行 if (!mappedHandler.applyPreHandle(processedRequest, response)) { return; } // Actually invoke the handler. //执行请求 mv = ha.handle(processedRequest, response, mappedHandler.getHandler()); ..................................... }
@Nullable protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception { if (this.handlerMappings != null) { for (HandlerMapping mapping : this.handlerMappings) { //文章开头说了 handlerMethod 是在 handlerExceutionChain 中,所以在这个代码里 HandlerExecutionChain handler = mapping.getHandler(request); if (handler != null) { return handler; } } } return null; }
@Override @Nullable public final HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception { //就是在这里获取的 handlerMethod 也就是请求的映射关系 Object handler = getHandlerInternal(request); if (handler == null) { handler = getDefaultHandler(); } if (handler == null) { return null; } // Bean name or resolved handler? if (handler instanceof String) { String handlerName = (String) handler; handler = obtainApplicationContext().getBean(handlerName); } //获取 执行链 把 handlerMethod 放入 HandlerExecutionChain HandlerExecutionChain executionChain = getHandlerExecutionChain(handler, request); if (logger.isTraceEnabled()) { logger.trace("Mapped to " + handler); } else if (logger.isDebugEnabled() && !request.getDispatcherType().equals(DispatcherType.ASYNC)) { logger.debug("Mapped to " + executionChain.getHandler()); } if (CorsUtils.isCorsRequest(request)) { CorsConfiguration globalConfig = this.corsConfigurationSource.getCorsConfiguration(request); CorsConfiguration handlerConfig = getCorsConfiguration(handler, request); CorsConfiguration config = (globalConfig != null ? globalConfig.combine(handlerConfig) : handlerConfig); executionChain = getCorsHandlerExecutionChain(request, executionChain, config); } return executionChain; }
@Override protected HandlerMethod getHandlerInternal(HttpServletRequest request) throws Exception { //根据request 获取 请求路径 里面东西还挺多,不多也就是获取路径的 String lookupPath = getUrlPathHelper().getLookupPathForRequest(request); this.mappingRegistry.acquireReadLock(); try { //获取 handlerMethod HandlerMethod handlerMethod = lookupHandlerMethod(lookupPath, request); return (handlerMethod != null ? handlerMethod.createWithResolvedBean() : null); } finally { this.mappingRegistry.releaseReadLock(); } }
@Nullable protected HandlerMethod lookupHandlerMethod(String lookupPath, HttpServletRequest request) throws Exception { List matches = new ArrayList<>(); //这里根据请求路径获取requsetMappingInfo 格式为 [{GET /xml, produces [application/xml]}] //请求方式,请求路径,响应类型 注意 现在这个类 是requestMappingHandlerMapping 的一个父类 // 说明 这也信息有可能是在 requestMappingHandlerMapping 初始化的时候放进去的. List directPathMatches = this.mappingRegistry.getMappingsByUrl(lookupPath); if (directPathMatches != null) { //获取 Match 的方法 Match 中包含 HandlerMethod addMatchingMappings(directPathMatches, matches, request); } if (matches.isEmpty()) { // No choice but to go through all mappings... addMatchingMappings(this.mappingRegistry.getMappings().keySet(), matches, request); } if (!matches.isEmpty()) { Comparator comparator = new MatchComparator(getMappingComparator(request)); matches.sort(comparator); Match bestMatch = matches.get(0); if (matches.size() > 1) { if (logger.isTraceEnabled()) { logger.trace(matches.size() + " matching mappings: " + matches); } if (CorsUtils.isPreFlightRequest(request)) { return PREFLIGHT_AMBIGUOUS_MATCH; } Match secondBestMatch = matches.get(1); if (comparator.compare(bestMatch, secondBestMatch) == 0) { Method m1 = bestMatch.handlerMethod.getMethod(); Method m2 = secondBestMatch.handlerMethod.getMethod(); String uri = request.getRequestURI(); throw new IllegalStateException( "Ambiguous handler methods mapped for '" + uri + "': {" + m1 + ", " + m2 + "}"); } } request.setAttribute(BEST_MATCHING_HANDLER_ATTRIBUTE, bestMatch.handlerMethod); handleMatch(bestMatch.mapping, lookupPath, request); // 发现返回的 handlerMethod 是 Match 属性 所以我们关注 matches 就行了 return bestMatch.handlerMethod; } else { return handleNoMatch(this.mappingRegistry.getMappings().keySet(), lookupPath, request); } }
private void addMatchingMappings(Collection mappings, List matches, HttpServletRequest request) { for (T mapping : mappings) { //这里又去获取了一次 requestMappingInfo 我以为不知道为啥又去获取了一次 T match = getMatchingMapping(mapping, request); if (match != null) { //这里创建了Match 点进去发现传了两个参数 一个是requestMapping 一个是 HandlerMethod //现在主要看下 this.mappingRegistry.getMappings().get(mapping)) matches.add(new Match(match, this.mappingRegistry.getMappings().get(mapping))); } } }
public Map getMappings() { return this.mappingLookup; } //到这里可以看到了 HandlerMethod 是从mappingLookup获取的 private final Map mappingLookup = new LinkedHashMap<>();
protected void invokeInitMethods(String beanName, final Object bean, @Nullable RootBeanDefinition mbd) throws Throwable { boolean isInitializingBean = (bean instanceof InitializingBean); if (isInitializingBean && (mbd == null || !mbd.isExternallyManagedInitMethod("afterPropertiesSet"))) { if (logger.isTraceEnabled()) { logger.trace("Invoking afterPropertiesSet() on bean with name '" + beanName + "'"); } if (System.getSecurityManager() != null) { try { AccessController.doPrivileged((PrivilegedExceptionAction) () -> { ((InitializingBean) bean).afterPropertiesSet(); return null; }, getAccessControlContext()); } catch (PrivilegedActionException pae) { throw pae.getException(); } } else { //这里就是入口 ((InitializingBean) bean).afterPropertiesSet(); } } if (mbd != null && bean.getClass() != NullBean.class) { String initMethodName = mbd.getInitMethodName(); if (StringUtils.hasLength(initMethodName) && !(isInitializingBean && "afterPropertiesSet".equals(initMethodName)) && !mbd.isExternallyManagedInitMethod(initMethodName)) { invokeCustomInitMethod(beanName, bean, mbd); } } }
@Override public void afterPropertiesSet() { //这堆配置 具体是啥我也不知道 this.config = new RequestMappingInfo.BuilderConfiguration(); this.config.setUrlPathHelper(getUrlPathHelper()); this.config.setPathMatcher(getPathMatcher()); this.config.setSuffixPatternMatch(this.useSuffixPatternMatch); this.config.setTrailingSlashMatch(this.useTrailingSlashMatch); this.config.setRegisteredSuffixPatternMatch(this.useRegisteredSuffixPatternMatch); this.config.setContentNegotiationManager(getContentNegotiationManager()); //看这里,调用了父类的 afterPropertiesSet(); super.afterPropertiesSet();(); }
@Override public void afterPropertiesSet() { //这里 initHandlerMethods(); } //这里 protected void initHandlerMethods() { //getCandidateBeanNames() 应该是获取了所有的beanName for (String beanName : getCandidateBeanNames()) { if (!beanName.startsWith(SCOPED_TARGET_NAME_PREFIX)) { //就是这里 processCandidateBean(beanName); } } handlerMethodsInitialized(getHandlerMethods()); } //根绝beanName处理的 protected void processCandidateBean(String beanName) { Class beanType = null; try { //获取当前bean的class 类型 beanType = obtainApplicationContext().getType(beanName); } catch (Throwable ex) { // An unresolvable bean type, probably from a lazy bean - let's ignore it. if (logger.isTraceEnabled()) { logger.trace("Could not resolve type for bean '" + beanName + "'", ex); } } //这里 重点 isHandler() 判断是否需要处理 if (beanType != null && isHandler(beanType)) { //假如是的话,继续 (重点) detectHandlerMethods(beanName); } } // 看到了,条件就是 当前类是否存在 @Controller @RequestMapping 注解 protected boolean isHandler(Class beanType) { return (AnnotatedElementUtils.hasAnnotation(beanType, Controller.class) || AnnotatedElementUtils.hasAnnotation(beanType, RequestMapping.class)); }
下面的代码就是最后了,注意看! 下面的代码比较绕,用的是java8的Lambda 表达式,假如对java8比较熟,看这段代码是无压力的 先把这几个方法的代码都贴出来,如下:
protected void detectHandlerMethods(Object handler) { Class handlerType = (handler instanceof String ? obtainApplicationContext().getType((String) handler) : handler.getClass()); if (handlerType != null) { //获取当前contorller 类型 Class userType = ClassUtils.getUserClass(handlerType); // 第一步 就是这里 执行selectMethods 这个方法 传递了一个行为(lambda表达式) Map methods = MethodIntrospector.selectMethods(userType, (MethodIntrospector.MetadataLookup) method -> { try { //第六步 return getMappingForMethod(method, userType); } catch (Throwable ex) { throw new IllegalStateException("Invalid mapping on handler class [" + userType.getName() + "]: " + method, ex); } }); if (logger.isTraceEnabled()) { logger.trace(formatMappings(userType, methods)); } //第七步 methods.forEach((method, mapping) -> { Method invocableMethod = AopUtils.selectInvocableMethod(method, userType); registerHandlerMethod(handler, invocableMethod, mapping); }); } } public static Map selectMethods(Class targetType, final MetadataLookup metadataLookup) { final Map methodMap = new LinkedHashMap<>(); Set> handlerTypes = new LinkedHashSet<>(); Class specificHandlerType = null; //判断是否存在代理 if (!Proxy.isProxyClass(targetType)) { specificHandlerType = ClassUtils.getUserClass(targetType); handlerTypes.add(specificHandlerType); } handlerTypes.addAll(ClassUtils.getAllInterfacesForClassAsSet(targetType)); //循环 第二步 目标 controller 正常情况就一个元素 for (Class currentHandlerType : handlerTypes) { final Class targetClass = (specificHandlerType != null ? specificHandlerType : currentHandlerType); // 调用 doWithMethods 第三步 ReflectionUtils.doWithMethods(currentHandlerType, method -> { //第五步 获取到了 method Method specificMethod = ClassUtils.getMostSpecificMethod(method, targetClass); T result = metadataLookup.inspect(specificMethod); if (result != null) { Method bridgedMethod = BridgeMethodResolver.findBridgedMethod(specificMethod); if (bridgedMethod == specificMethod || metadataLookup.inspect(bridgedMethod) == null) { methodMap.put(specificMethod, result); } } }, ReflectionUtils.USER_DECLARED_METHODS); } return methodMap; } public static void doWithMethods(Class clazz, MethodCallback mc, @Nullable MethodFilter mf) { // Keep backing up the inheritance hierarchy. //获取所有的方法 Method[] methods = getDeclaredMethods(clazz); for (Method method : methods) { if (mf != null && !mf.matches(method)) { continue; } try { //执行 selectMethods 方法中的 MethodFilter mf 第四步 mc.doWith(method); } catch (IllegalAccessException ex) { throw new IllegalStateException("Not allowed to access method '" + method.getName() + "': " + ex); } } if (clazz.getSuperclass() != null) { doWithMethods(clazz.getSuperclass(), mc, mf); } else if (clazz.isInterface()) { for (Class superIfc : clazz.getInterfaces()) { doWithMethods(superIfc, mc, mf); } } } //保存对应关系入口 protected void registerHandlerMethod(Object handler, Method method, T mapping) { this.mappingRegistry.register(mapping, handler, method); } //结束了 public void register(T mapping, Object handler, Method method) { this.readWriteLock.writeLock().lock(); try { HandlerMethod handlerMethod = createHandlerMethod(handler, method); assertUniqueMethodMapping(handlerMethod, mapping); //保存到 mappingLookup this.mappingLookup.put(mapping, handlerMethod); List directUrls = getDirectUrls(mapping); for (String url : directUrls) { //保存路径到urlLookup this.urlLookup.add(url, mapping); } // String name = null; if (getNamingStrategy() != null) { name = getNamingStrategy().getName(handlerMethod, mapping); addMappingName(name, handlerMethod); } CorsConfiguration corsConfig = initCorsConfiguration(handler, method, mapping); if (corsConfig != null) { this.corsLookup.put(handlerMethod, corsConfig); } this.registry.put(mapping, new MappingRegistration<>(mapping, handlerMethod, directUrls, name)); } finally { this.readWriteLock.writeLock().unlock(); } }