SpringMVC源码之Handler注册、获取以及请求controller中方法
总结
- 对requestMappingHandlerMapping进行initializeBean时register Handler
- http开始请求时,initHandlerMappings,DispatcherServlet 中handlerMappings赋值完成
- 最后在DispatcherServlet#doDispatch()中,用对应的HandlerAdapter和Handler通过反射去请求controller中方法
对requestMappingHandlerMapping进行initializeBean时register Handler
调用链:
AbstractApplicationContext#refresh() --> AbstractApplicationContext#finishBeanFactoryInitialization() --> DefaultListableBeanFactory#preInstantiateSingletons() --> AbstractBeanFactory#getBean() --> AbstractBeanFactory#doGetBean() --> AbstractAutowireCapableBeanFactory#createBean() --> AbstractAutowireCapableBeanFactory#doCreateBean() --> AbstractAutowireCapableBeanFactory#initializeBean() --> AbstractAutowireCapableBeanFactory#invokeInitMethods() --> RequestMappingHandlerMapping#afterPropertiesSet() --> AbstractHandlerMethodMapping#afterPropertiesSet() --> AbstractHandlerMethodMapping#initHandlerMethods() --> AbstractHandlerMethodMapping#processCandidateBean --> AbstractHandlerMethodMapping#detectHandlerMethods() --> RequestMappingHandlerMapping#registerHandlerMethod() --> AbstractHandlerMethodMapping#registerHandlerMethod()
在AbstractHandlerMethodMapping#initHandlerMethods()中先获取所有的beanName,再挑选出符合条件的进行处理
protected void initHandlerMethods() { //获取容器中所有beanName for (String beanName : getCandidateBeanNames()) { if (!beanName.startsWith(SCOPED_TARGET_NAME_PREFIX)) { processCandidateBean(beanName); } } handlerMethodsInitialized(getHandlerMethods()); }
判断是Handler的才继续调用detectHandlerMethods方法
protected void processCandidateBean(String beanName) { Class<?> beanType = null; ...... if (beanType != null && isHandler(beanType)) { detectHandlerMethods(beanName); } }
满足handler的条件是(RequestMappingHandlerMapping#isHandler()):@Controller或@RequestMapping进行注解
@Override protected boolean isHandler(Class<?> beanType) { return (AnnotatedElementUtils.hasAnnotation(beanType, Controller.class) || AnnotatedElementUtils.hasAnnotation(beanType, RequestMapping.class)); }
满足条件的,进行注册
RequestMappingHandlerMapping#registerHandlerMethod()
@Override protected void registerHandlerMethod(Object handler, Method method, RequestMappingInfo mapping) { super.registerHandlerMethod(handler, method, mapping); updateConsumesCondition(mapping, method); }
AbstractHandlerMethodMapping#registerHandlerMethod()
protected void registerHandlerMethod(Object handler, Method method, T mapping) { this.mappingRegistry.register(mapping, handler, method); }
完成注册。AbstractHandlerMethodMapping#register()
public void register(T mapping, Object handler, Method method) { this.readWriteLock.writeLock().lock(); try { HandlerMethod handlerMethod = createHandlerMethod(handler, method); validateMethodMapping(handlerMethod, mapping); Set<String> directPaths = AbstractHandlerMethodMapping.this.getDirectPaths(mapping); for (String path : directPaths) { this.pathLookup.add(path, mapping); } String name = null; if (getNamingStrategy() != null) { name = getNamingStrategy().getName(handlerMethod, mapping); addMappingName(name, handlerMethod); } CorsConfiguration config = initCorsConfiguration(handler, method, mapping); if (config != null) { config.validateAllowCredentials(); this.corsLookup.put(handlerMethod, config); } this.registry.put(mapping, new MappingRegistration<>(mapping, handlerMethod, directPaths, name)); } finally { this.readWriteLock.writeLock().unlock(); } }
initHandlerMappings
调用链:
Standardwrapper#initServlet() --> HttpServletBean#init() --> FrameworkServlet#initServletBean() --> FrameworkServlet#initWebApplicationContext() --> DispatcherServlet#onRefresh() --> DispatcherServlet#initStrategies() -->
DispatcherServlet#initHandlerMappings()
http请求时,先initHandlerMappings.
matchingBeans会存储获取到所有符合条件的,再给handlerMappings赋值
private void initHandlerMappings(ApplicationContext context) { this.handlerMappings = null; if (this.detectAllHandlerMappings) { // Find all HandlerMappings in the ApplicationContext, including ancestor contexts. Map<String, HandlerMapping> matchingBeans = BeanFactoryUtils.beansOfTypeIncludingAncestors(context, HandlerMapping.class, true, false); if (!matchingBeans.isEmpty()) { this.handlerMappings = new ArrayList<>(matchingBeans.values());// We keep HandlerMappings in sorted order. AnnotationAwareOrderComparator.sort(this.handlerMappings); } } }
其中BeanFactoryUtils.beansOfTypeIncludingAncestors(context, HandlerMapping.class, true, false);会先调用AbstractApplicationContext#getBeansOfType(),再调用DefaultListableB 56c eanFactory#getBeansOfType()
先获取beanName requestMappingHandlerMapping,再根据beanName(requestMappingHandlerMapping)从容器获取beanInstance。最后put到result中返回
@Override @SuppressWarnings("unchecked") public <T> Map<String, T> getBeansOfType( @Nullable Class<T> type, boolean includeNonSingletons, boolean allowEagerInit) throws BeansException { //获取requestMappingHandlerMapping String[] beanNames = getBeanNamesForType(type, includeNonSingletons, allowEagerInit); Map<String, T> result = CollectionUtils.newLinkedHashMap(beanNames.length); for (String beanName : beanNames) { try { ////再根据beanName(requestMappingHandlerMapping)从容器获取beanInstance Object beanInstance = getBean(beanName); if (!(beanInstance instanceof NullBean)) { result.put(beanName, (T) beanInstance); } } ...... return result; }
从而在initHandlerMappings给handlerMappings赋值完成
this.handlerMappings = new ArrayList<>(matchingBeans.values());
doDispatch
获取当前请求的handler和HandlerAdapter
DispatcherServlet#doDispatch()
mappedHandler = getHandler(processedRequest);
DispatcherServlet#getHandler()
protected HandlerExecutionChai 1b31 n getHandler(HttpServletRequest request) throws Exception { if (this.handlerMappings != null) { for (HandlerMapping mapping : this.handlerMappings) { HandlerExecutionChain handler = mapping.getHandler(request); if (handler != null) { return handler; } } } return null; }
通过反射方式请求controller中方法:
// Actually invoke the handler. mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
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 { ModelAndView mv = null; Exception dispatchException = null; try { processedRequest = checkMultipart(request); multipartRequestParsed = (processedRequest != request); // Determine handler for the current request. 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()); if (asyncManager.isConcurrentHandlingStarted()) { return; } applyDefaultViewName(processedRequest, mv); mappedHandler.applyPostHandle(processedRequest, response, mv); } catch (Exception ex) { dispatchException = ex; } catch (Throwable err) { // As of 4.3, we're processing Errors thrown from handler methods as well, // making them available for @ExceptionHandler methods and other scenarios. dispatchException = new NestedServletException("Handler dispatch failed", err); } processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException); } catch (Exception ex) { triggerAfterCompletion(processedRequest, response, mappedHandler, ex); } catch (Throwable err) { triggerAfterCompletion(processedRequest, response, mappedHandler, new NestedServletException("Handler processing failed", err)); } finally { if (asyncManager.isConcurrentHandlingStarted()) { // Instead of postHandle and afterCompletion if (mappedHandler != null) { mappedHandler.applyAfterConcurrentHandlingStarted(processedRequest, response); } } else { // Clean up any resources used by a multipart request. if (multipartRequestParsed) { cleanupMultipart(processedRequest); } } } }
- 7、SpringMVC源码分析(2):分析HandlerAdapter.handle方法,了解handler方法的调用细节以及@ModelAttribute注解
- SpringMVC源码分析(2):分析HandlerAdapter.handle方法,了解handler方法的调用细节以及@ModelAttribute注解
- springMvc源码学习之:spirngMvc获取请求参数的方法
- springMvc源码学习之:spirngMVC获取请求参数的方法2
- 详解SpringMVC中Controller的方法中参数的工作原理[附带源码分析]
- MVC路由规则以及前后台获取Action、Controller、ID名方法
- 注解:SpringMVC中表单参数的限定和获取表单参数以及获取request,response,session+方法返回值讲解
- 详解SpringMVC中Controller的方法中参数的工作原理[附带源码分析] – format丶
- SpringMVC获取请求参数的方法
- springmvc请求参数获取的几种方法
- SpringMVC获取请求参数的方法
- springMVC使用HandlerMethodArgumentResolver 自定义解析器实现请求参数绑定方法参数
- springMVC源码分析--AbstractControllerUrlHandlerMapping(六)
- springMVC源码分析--SimpleControllerHandlerAdapter(三)
- 详解SpringMVC中Controller的方法中参数的工作原理[附带源码分析]
- 【MVC - 参数原理】详解SpringMVC中Controller的方法中参数的工作原理[附带源码分析]
- Spring Controller 获取请求参数的几种方法
- springMvc 完美解决 multipart/form-data 方式提交请求 在 Filter 中 ServletRequest.getParameter方法 获取不到参数的问题
- springmvc请求参数获取的四种方法
- SpringMVC 使用HandlerMethodArgumentResolver自定义解析器实现请求数据绑定方法入参