源码剖析-【HandlerAdapter handle 方法解析】
1.handleInternal方法简析
前面分析了SpringMVC获取handler及HandlerAdapter的过程,接下来就要真正开始处理Controller了。
以AbstractHandlerMethodAdapter为例来来分析一下其具体的处理过程。
在此过程中会包含SpringMVC流程处理的的关键部分。例如参数获取及解析、异步处理、调用Controller中的方法、返回视图等等
public final ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
return handleInternal(request, response, (HandlerMethod) handler);
}
protected ModelAndView handleInternal(HttpServletRequest request,
HttpServletResponse response,
HandlerMethod handlerMethod) throws Exception {
ModelAndView mav;
// 1.检测当前请求,验证请求方法合法性和session合法性
checkRequest(request);
// Execute invokeHandlerMethod in synchronized block if required.
// 2.根据synchronizeOnSession值判断,当前请求是否需串行化访问。
if (this.synchronizeOnSession) {
HttpSession session = request.getSession(false);
if (session != null) {
// 获取最佳互斥锁,即同步当前回话对象;如未能获取到互斥锁,将返回HttpSession对象本身
Object mutex = WebUtils.getSessionMutex(session);
synchronized (mutex) {
mav = invokeHandlerMethod(request, response, handlerMethod);
}
}
else {
// No HttpSession available -> no mutex necessary
// 即无最佳互斥锁,也未能获取到HttpSession,则当前回话无需串行化访问
mav = invokeHandlerMethod(request, response, handlerMethod);
}
}
else {
// No synchronization on session demanded at all...
mav = invokeHandlerMethod(request, response, handlerMethod);
}
// 3.相应信息不包含Cache-Control
if (!response.containsHeader(HEADER_CACHE_CONTROL)) {
if (getSessionAttributesHandler(handlerMethod).hasSessionAttributes()) {
applyCacheSeconds(response, this.cacheSecondsForSessionAttributeHandlers);
}
else {
prepareResponse(response);
}
}
return mav;
}
这里会涉及到一部分异步操作的代码。具体的处理方法委托给了invokeHandlerMethod方法。
@Nullable
protected ModelAndView invokeHandlerMethod(HttpServletRequest request,
HttpServletResponse response, HandlerMethod handlerMethod) throws Exception {
ServletWebRequest webRequest = new ServletWebRequest(request, response);
try {
//WebDataBinderFactory --> 工厂类,为目标对象创建一个WebDataBinder实例
// 1.WebDataBinder继承了DataBinder类,为web请求提供了参数绑定服务
WebDataBinderFactory binderFactory = getDataBinderFactory(handlerMethod);
// 获取ModelFactory:
// 2.ModelFactory可以协助控制器在调用方法之前初始化模型,并在调用之后更新模型
ModelFactory modelFactory = getModelFactory(handlerMethod, binderFactory);
// 创建ServletInvocableHandlerMethod对象
// 3.ServletInvocableHandlerMethod继承并扩展了InvocableHandlerMethod
ServletInvocableHandlerMethod invocableMethod = createInvocableHandlerMethod(handlerMethod);
// 4.尝试绑定参数、返回值解析器
if (this.argumentResolvers != null) {
invocableMethod.setHandlerMethodArgumentResolvers(this.argumentResolvers);
}
if (this.returnValueHandlers != null) {
invocableMethod.setHandlerMethodReturnValueHandlers(this.returnValueHandlers);
}
invocableMethod.setDataBinderFactory(binderFactory);
invocableMethod.setParameterNameDiscoverer(this.parameterNameDiscoverer);
// 5.创建ModelAndViewContainer,并初始化Model对象
ModelAndViewContainer mavContainer = new ModelAndViewContainer();
mavContainer.addAllAttributes(RequestContextUtils.getInputFlashMap(request));
modelFactory.initModel(webRequest, mavContainer, invocableMethod);
mavContainer.setIgnoreDefaultModelOnRedirect(this.ignoreDefaultModelOnRedirect);
// 6.异步请求相关
AsyncWebRequest asyncWebRequest = WebAsyncUtils.createAsyncWebRequest(request, response);
asyncWebRequest.setTimeout(this.asyncRequestTimeout);
WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);
asyncManager.setTaskExecutor(this.taskExecutor);
asyncManager.setAsyncWebRequest(asyncWebRequest);
asyncManager.registerCallableInterceptors(this.callableInterceptors);
asyncManager.registerDeferredResultInterceptors(this.deferredResultInterceptors);
if (asyncManager.hasConcurrentResult()) {
Object result = asyncManager.getConcurrentResult();
mavContainer = (ModelAndViewContainer) asyncManager.getConcurrentResultContext()[0];
asyncManager.clearConcurrentResult();
if (logger.isDebugEnabled()) {
logger.debug("Resume with async result ["
+ (result instanceof CharSequence ? "\"" + result + "\"" : result) + "]");
}
invocableMethod = invocableMethod.wrapConcurrentResult(result);
}
// 7.调用Controller中的具体方法并处理返回值
invocableMethod.invokeAndHandle(webRequest, mavContainer);
if (asyncManager.isConcurrentHandlingStarted()) {
return null;
}
// 8.返回ModelAndView对象
return getModelAndView(mavContainer, modelFactory, webRequest);
}
finally {
// 完成请求后续处理,并将当前请求置为未激活
webRequest.requestCompleted();
}
}
invokeHandlerMethod方法还是很复杂的,下面我们对该方法进行详细的分析
2.getModelFactory方法
private ModelFactory getModelFactory(HandlerMethod handlerMethod, WebDataBinderFactory binderFactory) {
// 1.处理@SessionAttributes注解
SessionAttributesHandler sessionAttrHandler = getSessionAttributesHandler(handlerMethod);
Class<?> handlerType = handlerMethod.getBeanType();
// 2.处理@ModelAttribute注解
Set<Method> methods = this.modelAttributeCache.get(handlerType);
if (methods == null) {
methods = MethodIntrospector.selectMethods(handlerType, MODEL_ATTRIBUTE_METHODS);
this.modelAttributeCache.put(handlerType, methods);
}
List<InvocableHandlerMethod> attrMethods = new ArrayList<>();
// Global methods first
// 3.优先处理全局@ModelAttribute注解的方法,例如被@ControllerAdvice标注的类中存在被@ModelAttribute注解的方法,则优先处理
this.modelAttributeAdviceCache.forEach((clazz, methodSet) -> {
if (clazz.isApplicableToBeanType(handlerType)) {
Object bean = clazz.resolveBean();
for (Method method : methodSet) {
attrMethods.add(createModelAttributeMethod(binderFactory, bean, method));
}
}
});
// 4.循环所有标注了@ModelAttribute注解的方法,并创建InvocableHandlerMethod对象
// InvocableHandlerMethod:负责具体的HandlerMethod的调用、参数解析等工作
for (Method method : methods) {
Object bean = handlerMethod.getBean();
attrMethods.add(createModelAttributeMethod(binderFactory, bean, method));
}
// 5.返回ModelFactory对象
// Mo