SpringMVC源码之Handler注册、获取以及请求controller中方法

总结

  1. 对requestMappingHandlerMapping进行initializeBean时register Handler
  2. http开始请求时,initHandlerMappings,DispatcherServlet 中handlerMappings赋值完成
  3. 最后在DispatcherServlet#doDispatch()中,用对应的HandlerAdapter和Handler经过反射去请求controller中方法

对requestMappingHandlerMapping进行initializeBean时register Handler

调用链:ios

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()app

在AbstractHandlerMethodMapping#initHandlerMethods()中先获取全部的beanName,再挑选出符合条件的进行处理cors

protected void initHandlerMethods() {
    //获取容器中全部beanName
	for (String beanName : getCandidateBeanNames()) {
		if (!beanName.startsWith(SCOPED_TARGET_NAME_PREFIX)) {
			processCandidateBean(beanName);
		}
	}
	handlerMethodsInitialized(getHandlerMethods());
}

判断是Handler的才继续调用detectHandlerMethods方法async

protected void processCandidateBean(String beanName) {
	Class<?> beanType = null;
    ......
	if (beanType != null && isHandler(beanType)) {
		detectHandlerMethods(beanName);
	}
}

知足handler的条件是(RequestMappingHandlerMapping#isHandler()):@Controller或@RequestMapping进行注解ide

@Override
protected boolean isHandler(Class<?> beanType) {
	return (AnnotatedElementUtils.hasAnnotation(beanType, Controller.class) ||
			AnnotatedElementUtils.hasAnnotation(beanType, RequestMapping.class));
}

知足条件的,进行注册
RequestMappingHandlerMapping#registerHandlerMethod()post

@Override
protected void registerHandlerMethod(Object handler, Method method, RequestMappingInfo mapping) {
	super.registerHandlerMethod(handler, method, mapping);
	updateConsumesCondition(mapping, method);
}

AbstractHandlerMethodMapping#registerHandlerMethod()this

protected void registerHandlerMethod(Object handler, Method method, T mapping) {
	this.mappingRegistry.register(mapping, handler, method);
}

完成注册。AbstractHandlerMethodMapping#register()spa

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

调用链:code

Standardwrapper#initServlet() --> HttpServletBean#init() --> FrameworkServlet#initServletBean() --> FrameworkServlet#initWebApplicationContext() --> DispatcherServlet#onRefresh() --> DispatcherServlet#initStrategies() -->
DispatcherServlet#initHandlerMappings()ip

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(),再调用DefaultListableBeanFactory#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 HandlerExecutionChain 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);
			}
		}
	}
}