总结

  1. 对requestMappingHandlerMapping进行initializeBean时register Handler
  2. http开始请求时,initHandlerMappings,DispatcherServlet 中handlerMappings赋值完成
  3. 最后在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(),再调用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);
}
}
}
}

SpringMVC源码之Handler注册、获取以及请求controller中方法的更多相关文章

  1. springMVC源码分析--AbstractHandlerMethodMapping注册url和HandlerMethod对应关系(十一)

    在上一篇博客springMVC源码分析--AbstractHandlerMethodMapping获取url和HandlerMethod对应关系(十)中我们简单地介绍了获取url和HandlerMet ...

  2. 7、SpringMVC源码分析(2):分析HandlerAdapter.handle方法,了解handler方法的调用细节以及@ModelAttribute注解

    从上一篇 SpringMVC源码分析(1) 中我们了解到在DispatcherServlet.doDispatch方法中会通过 mv = ha.handle(processedRequest, res ...

  3. SpringMVC源码剖析(四)- DispatcherServlet请求转发的实现

    SpringMVC完成初始化流程之后,就进入Servlet标准生命周期的第二个阶段,即“service”阶段.在“service”阶段中,每一次Http请求到来,容器都会启动一个请求线程,通过serv ...

  4. 6、SpringMVC源码分析(1):分析DispatcherServlet.doDispatch方法,了解总体流程

    所有的http请求都会交给DispatcherServlet类的doDispatch方法进行处理,将DispatcherServlet.doDispatch函数的javadoc复制到下面: /* * ...

  5. springMVC源码阅读-通过画图理解一个请求生命周期(十二)

  6. springMVC源码分析--DispatcherServlet请求获取及处理

    在之前的博客springMVC源码分析--容器初始化(二)DispatcherServlet中我们介绍过DispatcherServlet,是在容器初始化过程中出现的,我们之前也说过Dispatche ...

  7. springMVC源码分析--HandlerInterceptor拦截器调用过程(二)

    在上一篇博客springMVC源码分析--HandlerInterceptor拦截器(一)中我们介绍了HandlerInterceptor拦截器相关的内容,了解到了HandlerInterceptor ...

  8. springMVC源码学习之addFlashAttribute源码分析

    本文主要从falshMap初始化,存,取,消毁来进行源码分析,springmvc版本4.3.18.关于使用及验证请参考另一篇jsp取addFlashAttribute值深入理解即springMVC发r ...

  9. springMVC源码分析--动态样式ThemeResolver(二)

    在上一篇博客springMVC源码分析--动态样式ThemeResolver(一)中我们介绍了多样式ThemeResolver的使用方法,接下来我们对源码进行简单的分析一下. ThemeResolve ...

随机推荐

  1. bootStrap小结1

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  2. RLP序列化算法

    RLP RLP(Recursive Length Prefix)递归长度前缀编码,是由以太坊提出的序列化/反序列化标准,相比json格式体积更小,相比protobuf对多语言的支持更强. RLP将数据 ...

  3. js 实现 input file 文件上传

    <!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml"> <head runat=&qu ...

  4. Storm入门教程汇总

    http://www.aboutyun.com/thread-8059-1-1.html

  5. sqlserver安装失败,此计算机上安装了 Microsoft Visual Studio 2008 的早期版本解决方法

    安装sql server 2008 management,提示错误:此计算机上安装了 Microsoft Visual Studio 2008 的早期版本.请在安装 SQL Server 2008 前 ...

  6. lerna管理前端模块实践

    最近在工作中使用了 lerna 进行前端包的管理,效率提升了很多.所以打算总结一下最近几个月使用 lerna 的一些心得.有那些不足的地方,请包涵. 该篇文章主要包括在使用 lerna 的一些注意事项 ...

  7. PowerShell 定时输出citrix desktop昨日连接会话

    asnp citrix*$now_date = [datetime]::Today$day2 = [datetime]::Today - [TimeSpan]::FromHours(24)$fiel_ ...

  8. 【Azure媒体服务 Azure Media Service】Azure Media Service中Stream Endpoint 说明 (流式处理终结点)

    Azure 媒体服务是一个基于云的媒体工作流平台,用于生成需要编码.打包.内容保护和直播活动广播的解决方案. 在视频的直播,点播方案中,媒体服务的架构主要由三部分构成: 推流端,把本地视频或直播内容推 ...

  9. C# 判断当前目录是否存在不存在则创建

    /// <summary> /// 判断目录是否存在不存在则创建 /// </summary> /// <param name="Path">& ...

  10. Linux运维学习第三周记

    日落狐狸眠冢上 夜归儿女笑灯前 人生有酒须当醉 一滴何曾到九泉 愿醉卧沙场可未有匹夫之勇. 第三周学记 第三周主要学习正则表达式和Shell编程 1.正则表达式基本字符 2.扩展正则表达式 3.gre ...