SpringMVC及其HandlerMapping、HandlerInterceptor、HandlerAdapter等组件的原理解析
SpringMVC的原理
加载的过程
关于加载,在SpringIOC的加载过程中,并不会直接将HandlerMapping等组件给加载进去,而是在第一次请求的时候,进行初始化
SpringMVC核心类,DispatcherServlet的类图
关于DispatcherServlet的初始化过程:由HttpServletBean调用init(),再由FrameworkServlet实现initServletBean(),最终由DispatcherServlet实现onRefresh(),并在其中加载初始化各个组件。
protected void initStrategies(ApplicationContext context) { initMultipartResolver(context);//加载上传解析器 initLocaleResolver(context); initThemeResolver(context);// initHandlerMappings(context);//加载初始化HandlerMapping initHandlerAdapters(context);//加载初始化HandlerAdapter initHandlerExceptionResolvers(context);//加载初始化HandlerException initRequestToViewNameTranslator(context); initViewResolvers(context); initFlashMapManager(context); }
HandlerMapping初始化过程
通过SpringBean工厂获取已经加载了的HandlerMapping的实现类对象
private void initHandlerMappings(ApplicationContext context) { this.handlerMappings = null; if (this.detectAllHandlerMappings) { // Find all HandlerMappings in the ApplicationContext, including ancestor contexts. //通过SpringIOC获取已经加载了的HandlerMapping的实现类对象 Map<String, HandlerMapping> matchingBeans = BeanFactoryUtils.beansOfTypeIncludingAncestors(context, HandlerMapping.class, true, false); //省略。。。 }
在初始化的过程中,通过类型type从SpringIOC容器中去获取HandlerMapping的实现类
SpringBoot默认加载了5个HandlerMapping的实现类:
RequestMappingHandlerMapping:通过@RequestMapping映射的路径寻找到对应方法的类
WelcomePageHandlerMapping:配置默认欢迎页时需要配置的类
BeanNameUrlHandlerMapping:和下面的SimplerUrlHandlerMapping类似,都是通过xml文件的方式配置url,将url与对应的Controller的方法进行绑定
SimpleUrlHandlerMapping:如上所说
在SpringMVC初始化之前,SpringIOC加载RequestMappingHandlerMapping的时候,在AbstractAutowireCapableBeanFactory构建好对象,并进行初始化(initializeBean())的时候,将各个@RequestMapping对应的Controller方法映射的String地址给注册到RequestMappingHandlerMapping中
protected void detectHandlerMethods(Object handler) { //... Map<Method, T> methods = MethodIntrospector.selectMethods(userType, (MethodIntrospector.MetadataLookup<T>) method -> { try { return getMappingForMethod(method, userType); } catch (Throwable ex) { throw new IllegalStateException("Invalid mapping on handler class [" + userType.getName() + "]: " + method, ex); } }); //... // methods.forEach((method, mapping) -> { Method invocableMethod = AopUtils.selectInvocableMethod(method, userType); registerHandlerMethod(handler, invocableMethod, mapping); }); } } protected void registerHandlerMethod(Object handler, Method method, T mapping) { //将对应的url映射到对应的Controller方法上 this.mappingRegistry.register(mapping, handler, method); }
HandlerInterceptor在加载的时候
HandlerInterceptor随着RequestMappingHandlerMapping在SpringIOC中创建对象的同时,进行加载与初始化
protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) throws BeanCreationException { // 实例化对象 BeanWrapper instanceWrapper = null; if (instanceWrapper == null) { //在实例化对象的包装器的时候,将HandlerInterceptor进行了加载与初始化 instanceWrapper = createBeanInstance(beanName, mbd, args); } Object bean = instanceWrapper.getWrappedInstance(); // 对实例对象初始化 Object exposedObject = bean; try { populateBean(beanName, mbd, instanceWrapper); exposedObject = initializeBean(beanName, exposedObject, mbd); } // return exposedObject; }
HandlerAdapter在加载的时候
和HandlerMapping的流程类似,都是现在SpringIOC中加载、初始化对象,然后在SpringMVC第一次请求来的时候,将HandlerAdapter的实现对象初始化到SpringMVC的上下文中。
HandlerAdapter的常见实现类:
RequestMappingHandlerAdapter:通过RequestMapping请求的处理器
HttpRequesthandlerAdapter:静态资源处理器
SimpleControllerHandlerAdapter:Controller接口实现类的处理器,处理Controller实现类的请求
``
SpringMVC的工作流程
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); //1.通过请求的url找到应该使用哪个HandlerMapping,并获取到HandlerMapping的HandlerExecutionChain //HandlerInterceptor就是在这里进行初始化的,每次请求来时,都会在HandlerExecutionChain对象中赋值 mappedHandler = getHandler(processedRequest); //2.通过HandlerMethod找到其应该用哪个HandlerAdapter HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler()); //3.执行HandlerInterptor中的preHandler if (!mappedHandler.applyPreHandle(processedRequest, response)) { return; } //4.通过HandlerAdapter调用Contoller中的具体方法,并返回ModelAndView //如果不返回ModelAndView,则直接响应用户了 //在这里面,有HandlerAdapter决定了如果处理请求体、响应体 mv = ha.handle(processedRequest, response, mappedHandler.getHandler()); if (asyncManager.isConcurrentHandlingStarted()) { return; } applyDefaultViewName(processedRequest, mv); //5.执行HandlerInterptor中的postHandler mappedHandler.applyPostHandle(processedRequest, response, mv); } catch (Exception ex) { dispatchException = ex; } processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException); } }