SpringMVC 源码分析(二)

本文主要讲的是Controller中的@RequestMapping方法是如何生成映射供后面调用的过程,其中最主要的处理类就是requestMappingHandlerMapping,先从requestMappingHandlerMapping 说起,下面先贴下requestMappingHandlerMapping的初始化及生成Controller调用映射的流程图。

我们以SpringBoot为例,当服务一系列的配置资源加载解析完毕,在启动时会调SpringApplication类的refreshContext(context)方法:

该方法名为刷新应用上下文,主要用来设置容器功能特性以及初始化并注册bean,设置监听器等。springBoot默认的WEB容器是AnnotationConfigServletWebServerApplicationContext,所以最终进入父类AbstractApplicationContext中的refresh进行处理。

我们的controller映射也是在实例化所有单例的这个方法中完成的,所以我们直接跳到实例化并注册bean这里。AbstractApplicationContext#finishBeanFactoryInitialization 继续进入DefaultListableBeanFactory#preInstantiateSingletons遍历所有已经注册到容器的beanDefinitionName,根据beanDefinitionName获取到BeanDefinition,并实例化bean。我们重点关注beanName为requestMappingHandlerMapping的实例化过程,实例化从getBean方法开始,至于requestMappingHandlerMapping是什么时候加载到容器里的呢?记为问题1,我们下文再说

bean的实例化无非就是从BeanDefinition中获取bean的信息,执行一系列的BeanPostProcessor,

最后通过构造器反射创建bean,注入bean的属性等等,这里不多赘述。

我们主要讲requestMappingHandlerMapping实例化后的操作:

AbstractAutowireCapableBeanFactory#doCreateBean方法中调用了initializeBean方法,此时的beanName为requestMappingHandlerMapping:

继续进入AbstractAutowireCapableBeanFactory#initializeBean方法中

 继续深入AbstractAutowireCapableBeanFactory#invokeInitMethods

 进入RequestMappingHandlerMapping的afterPropertiesSet()方法:

 最终调用父类AbstractHandlerMethodMapping的afterPropertiesSet()方法,最终调用了processCandidateBean方法,processCandidateBean方法是用来过滤所有加了@Controller和@RequestMapping注解,包括GetMapping(本质还是RequestMapping)等,并注册进map映射。

进入到processCandidateBean方法中,可以看到先根据beanName获取Class对象,然后去判断是否有@Controller和@RequestMapping注解,有的话就是Controller,比如我们新建一个HelloController,有以上注解,那么就会通过isHandler方法过滤,然后继续调用detectHandlerMethods方法进一步处理:

 isHandler方法如图:

进入detectHandlerMethods方法中,可以看到先去找Controller类的所有处理器方法,然后调用getMappingForMethod方法将处理器方法封装成RequestMappingInfo对象,最后以处理器方法对象为key,RequestMappingInfo对象为value存入map映射中,最后遍历map注册,这里面Spring用了几个回调函数,采用了接口内部实现类来实现,对代码的阅读造成了一定的难度,其实搞懂了java的语法,还是很容易理解的:

我们先看MethodIntrospector#selectMethods方法 ,先通过ReflectionUtils.doWithMethods获取Controller所有的方法,然后遍历这些方法进行封装,最后再放入map中

进入ReflectionUtils.doWithMethods方法:再回到MethodIntrospector#selectMethods方法中,metadataLookup.inspect(specificMethod)调用的就是外层的getMappingForMethod方法

RequestMappingInfo的部分属性如下

 回到AbstractHandlerMethodMapping#detectHandlerMethods中,遍历最后得到的map进行注册

进入最终的register方法,最关键的就是这三个map,mappingLookup、urlLookup(底层也是map)、corsLookup。我们通常在页面发起一个request请求,springMVC会先解析url,然后通过url去urlLookup中找对应的mapping,再根据mapping去mappingLookup中找Controller的Mapping处理方法HandlerMethod,如果有cros配置,那么最后再根据HandlerMethod找到对应的配置,最后通过反射最终调用到我们Controller的@RequestMapping方法。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值