springMvc - Mapping匹配过程
2019-08-22 19:52:07   32  举报             
     
         
 AI智能生成
  SpringMVC请求过程,当一个请求传来时,Spring都做了什么
    作者其他创作
 大纲/内容
  一个get请求,/myjava/game/games.do?gameId=1时,springMVC会做什么  
     1. 扫描controller注解和requstMapping注解的类
初始化成handlerMethod
    
    初始化成handlerMethod
 HttpServletBean.init
将配置参数映射到此servlet的bean属性,并调用子类初始化。
FrameworkServlet.initServletBean
FrameworkServlet.initWebApplicationContext
初始化WebApplicationContext
FrameworkServlet.createWebApplicationContext
创建WebApplicationContext
FrameworkServlet.configureAndRefreshWebApplicationContext
AbstractApplicationContext.refresh
spring上下文初始化bean的方法
AbstractApplicationContext.finishBeanFactoryInitialization
完成此上下文的全部bean工厂初始化
DefaultListbleBeanFactory.preInstantiateSingletons
批量实例化单例模式bean,获取bean
AbstractBeanFactory.getBean
AbstractBeanFactory.doGetBean
DefaultSingletonBeanRegistry.getSingleton
AbstractAutowireCapableBeanFactory.createBean
AbstractAutowireCapableBeanFactory.doCreateBean
AbstractAutowireCapableBeanFactory.initializeBean
AbstractAutowireCapableBeanFactory.invokeInitMethods
RequestMappingHandlerMapping.afterPropertiesSet
AbstractHandlerMethodMapping.afterPropertiesSet
初始化时检查方法处理器
    
    将配置参数映射到此servlet的bean属性,并调用子类初始化。
FrameworkServlet.initServletBean
FrameworkServlet.initWebApplicationContext
初始化WebApplicationContext
FrameworkServlet.createWebApplicationContext
创建WebApplicationContext
FrameworkServlet.configureAndRefreshWebApplicationContext
AbstractApplicationContext.refresh
spring上下文初始化bean的方法
AbstractApplicationContext.finishBeanFactoryInitialization
完成此上下文的全部bean工厂初始化
DefaultListbleBeanFactory.preInstantiateSingletons
批量实例化单例模式bean,获取bean
AbstractBeanFactory.getBean
AbstractBeanFactory.doGetBean
DefaultSingletonBeanRegistry.getSingleton
AbstractAutowireCapableBeanFactory.createBean
AbstractAutowireCapableBeanFactory.doCreateBean
AbstractAutowireCapableBeanFactory.initializeBean
AbstractAutowireCapableBeanFactory.invokeInitMethods
RequestMappingHandlerMapping.afterPropertiesSet
AbstractHandlerMethodMapping.afterPropertiesSet
初始化时检查方法处理器
 AbstractHandlerMethodMapping.initHandlerMethods
扫描ApplicationContext中的bean,检测和注册处理程序方法。
程序启动时执行,主要用于区分出controller和requestmapping注解的方法
    扫描ApplicationContext中的bean,检测和注册处理程序方法。
程序启动时执行,主要用于区分出controller和requestmapping注解的方法
 获取所有beanNames放入数组
这里获取的是springIOC中全部的Bean
包含controller,service,dao等一系列我们注册的类
    这里获取的是springIOC中全部的Bean
包含controller,service,dao等一系列我们注册的类
 遍历beanNames,调用RequestMappingHandlerMapping.isHandler
通过AnnotationUtils.findAnnotation(beanType, Controller.class)
处理controller注解和RequestMapping注解
    
    通过AnnotationUtils.findAnnotation(beanType, Controller.class)
处理controller注解和RequestMapping注解
 (AnnotationUtils.findAnnotation(beanType, Controller.class) != null)
(AnnotationUtils.findAnnotation(beanType, RequestMapping.class) != null)
    
    (AnnotationUtils.findAnnotation(beanType, RequestMapping.class) != null)
 从findAnnotationCacheMap中获取该bean和controller注解    
     findAnnotationCache 是一个线程安全的map,用于存放已经找到的AnnotationCacheKey  
     如果未取到值,则调用findAnnotation判断该Bean是否包含该注解    
     1. clazz.getDeclaredAnnotations()
常规的获取注解的方法
    常规的获取注解的方法
 2. 遍历注解数组,判断ann.annotationType().equals(annotationType)
此处的annotationType为controller和requestMapping,如果找到直接返回
    此处的annotationType为controller和requestMapping,如果找到直接返回
 3. 如果上面的遍历没有找到,则判断是否为JDK提供的注解,并且add到一个Set visited中    
     visited,用于保存已经访问过的annotation  
     4. 获取类的全部接口interface,判断接口的注解  
     5. 判断父类,是否包含此注解  
     如果找到值,则set到findAnnotationCacheMap中  
     detectHandlerMethods
在处理程序中寻找处理程序方法。
    
    在处理程序中寻找处理程序方法。
 1. 获取handler的Class对象
(handler instanceof String ? getApplicationContext().getType((String) handler) : handler.getClass()
比如此处获取的是GameController
    (handler instanceof String ? getApplicationContext().getType((String) handler) : handler.getClass()
比如此处获取的是GameController
 2. HandlerMethodSelectorselectMethods
选择处理器方法,其实就是获取该类GameController下的全部方法
  
    选择处理器方法,其实就是获取该类GameController下的全部方法
 3.  registerHandlerMethod
遍历GameController下的全部方法来调用该方法
注册到HandlerMethodMapping中
    
    遍历GameController下的全部方法来调用该方法
注册到HandlerMethodMapping中
 根据传入的类和方法,以及方法对应的requstmapping路径创建一个HandlerMethod方法处理器类
其实是一个方法对应一个处理器,如果controller中包含多个方法,会创造多个HandlerMethod类,只不过他们的bean属性是相同的
    
    其实是一个方法对应一个处理器,如果controller中包含多个方法,会创造多个HandlerMethod类,只不过他们的bean属性是相同的
 HandlerMethod    
     private final Object bean;  
     private final BeanFactory beanFactory; 该bean的工厂
  
     private final Class<?> beanType;  controller  
     private final Method method; 请求路径对应的方法  
     this.bridgedMethod = handlerMethod.bridgedMethod;  
     private final MethodParameter[] parameters;  
     将该方法处理器类放入名为handlerMethods的Map中    
     key : requestMappingInfo  
     value : HandlerMethod类  
     将请求路径放入urlMap中    
     key : Set<String>类型的请求路径  
     value : requestMappingInfo    
     封装以下请求映射条件  
     匹配方式 : Patterns  
     请求方法 : method  
     请求参数 : params  
     url请求头 : headers  
     Consumes  
     Produces  
     updateNameMap
将方法处理器放入nameMap中
    将方法处理器放入nameMap中
 key : GC#方法名  
     value : HandlerMethod类  
     getHandlerMethods  
     handlerMethodsInitialized  
     2. 初始化handlerMapping    
     DispatcherServlet.initStrategies
初始化该servlet使用的策略对象
    初始化该servlet使用的策略对象
 initMultipartResolver(context);  
     initLocaleResolver(context);  
     initThemeResolver(context);  
     initHandlerMappings(context);
初始化该类使用的HandlerMappings。
如果在BeanFactory中没有为这个名称空间定义HandlerMapping bean,
我们默认为BeanNameUrlHandlerMapping。
    
    初始化该类使用的HandlerMappings。
如果在BeanFactory中没有为这个名称空间定义HandlerMapping bean,
我们默认为BeanNameUrlHandlerMapping。
 BeanFactoryUtils.beansOfTypeIncludingAncestors(context, HandlerMapping.class, true, false);
在applicationContext中查找全部的handlerMapping,并赋值给handlerMappings集合
  
    在applicationContext中查找全部的handlerMapping,并赋值给handlerMappings集合
 initHandlerAdapters(context);  
     initHandlerExceptionResolvers(context);  
     initRequestToViewNameTranslator(context);  
     initViewResolvers(context);  
     initFlashMapManager(context);  
     3. 拦截分发前端请求    
     FrameworkServlet.service    
     获取请求方式 get/post/patch等  
     patch进入FrameworkServlet.processRequest  
     否则进入httpServlet.service    
     根据请求方式调用相应方法.如doGet  
     4. 根据请求查找对应的handlerMethod
并返回ModelAndView
    并返回ModelAndView
 例如 : 调用FrameworkServlet.doGet    
     FrameworkServlet.processRequest : 处理请求
FrameworkServlet重写了post,get等请求,交由processRequest方法处理
    FrameworkServlet重写了post,get等请求,交由processRequest方法处理
 DispatcherServlet.doService    
     向request中放入一些值,方便在handler中获取  
     DispatcherServlet.doDispatch
这步执行完之后,response中就包含了返回值
    这步执行完之后,response中就包含了返回值
 checkMultipart(request); 处理是否是文件上传请求  
     DispatcherServlet.getHandler
返回的是一个HandlerExecutionChain(执行链)
    返回的是一个HandlerExecutionChain(执行链)
到这里,我们根据request的请求路径获得到了路径对应Controller和方法
 1. 遍历handlerMappings    
     HandlerMapping接口,抽象类AbstractHandlerMapping  
     1.  RequestMappingHandlerMapping  
     2. BeanNameUrlHandlerMaping  
     3. SimpleUrlHandlerMapping  
     AbstractHandlerMapping.getHandler
查询请求的处理器执行链
    查询请求的处理器执行链
 1. AbstractHandlerMethodMapping.getHandlerInternal 
查找给定请求的处理程序方法。返回HandlerMethod类
    
    查找给定请求的处理程序方法。返回HandlerMethod类
 getUrlPathHelper 
用于URL路径匹配的Helper类。提供对RequestDispatcher include中的URL路径的支持,并支持一致的URL解码。
  
    用于URL路径匹配的Helper类。提供对RequestDispatcher include中的URL路径的支持,并支持一致的URL解码。
 getLookupPathForRequest
    
     getPathWithinServletMapping(request)
返回给定请求的servlet映射中的路径,
从request获取到/game/games.do请求路径
    
    返回给定请求的servlet映射中的路径,
从request获取到/game/games.do请求路径
 getPathWithinApplication(request)
返回给定请求的web应用程序内的路径。/game/games.do
    
    返回给定请求的web应用程序内的路径。/game/games.do
 getContextPath : 获取请求根目录/myjava  
     getRequestUri : 获取请求路径 (request.getRequestURI())  
     decodeAndCleanUriString : 解码提供的URI字符串,并去除';'后面的任何无关部分。  
     getRemainingPath : 去除掉请求路径中的项目名称等
  
     getServletPath(request)
request.getServletPath()
返回servlet请求路径 /game/games.do
  
    request.getServletPath()
返回servlet请求路径 /game/games.do
 getRemainingPath  
     getPathWithinApplication 如果路径不为一个空字符串,则进入此方法  
     lookupHandlerMethod 
查找当前请求的最佳匹配处理程序方法。
如果找到多个匹配项,则选择最佳匹配项。
也就是根据上一步获取的路径找到最佳匹配的包装了Controller的HandlerMethod
    
    查找当前请求的最佳匹配处理程序方法。
如果找到多个匹配项,则选择最佳匹配项。
也就是根据上一步获取的路径找到最佳匹配的包装了Controller的HandlerMethod
 根据key /game/games.do 从urlMap中获取直接匹配    
     urlMap中存的是全部的requestMapping地址  
     addMatchingMappings : 如果urlmap中获取到匹配的地址,则进入addMatchingMappings
    
     getMatchingMapping
遍历获取urlMap的匹配结果来调用此方法
    
    遍历获取urlMap的匹配结果来调用此方法
 getMatchingCondition : 从requestMappingInfo中获取这个url的详情,包括参数,请求头,请求方法等  
     通过一系列参数,new一个新的requestMappingInfo并返回  
     new Match(match, this.handlerMethods.get(mapping))
从AbstractHandlerMethodMapping.handlerMethods的map中获取handlerMethod然后new 一个Match
    
    从AbstractHandlerMethodMapping.handlerMethods的map中获取handlerMethod然后new 一个Match
 Match是AbstractHandlerMethodMapping的一个内部类
一个用于匹配HandlerMethod及其映射的薄包装,在当前请求的上下文中与比较器比较最佳匹配。
  
    一个用于匹配HandlerMethod及其映射的薄包装,在当前请求的上下文中与比较器比较最佳匹配。
 private final T mapping;  
     private final HandlerMethod handlerMethod;  
     添加Match进集合 matches  
     如果集合matches有多个结果,抛出IllegalStateException异常,说明请求遇到了多个匹配项,如果不进入,则到第四步  
     RequestMappingInfoHandlerMapping.handleMatch
向request中set一些参数
    向request中set一些参数
 super.handleMatch(info, lookupPath, request)
先调用父类 AbstractHandlerMethodMapping的handlerMatch方法
    先调用父类 AbstractHandlerMethodMapping的handlerMatch方法
 request.setAttribute(HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE, lookupPath); 将路径set到request中  
     将一些参数set进request中,如最佳匹配模式,URI模板变量属性
  
     return HandlerMethod.createWithResolvedBean
返回一个新的保存了controller的HandlerMethod
    返回一个新的保存了controller的HandlerMethod
 HandlerMethod  
     根据bean从Bean工厂中getBean,也就是实例化controller bean  
     return new HandlerMethod  
     2. return AbstractHandlerMapping.getHandlerExecutionChain(处理器controller,request)
构建一个新的HandlerExecutionChain(处理程序执行链,由处理程序对象和任何处理程序拦截器组成。)
    
    构建一个新的HandlerExecutionChain(处理程序执行链,由处理程序对象和任何处理程序拦截器组成。)
 如果handler是一个执行链,则直接使用此,否则根据handler创建一个执行链    
     HandlerExecutionChain的构造方法
HandlerExecutionChain(Object handler, HandlerInterceptor... interceptors)
在本例中执行到此步只有一个请求方法为games,ganmeController的handler
    HandlerExecutionChain(Object handler, HandlerInterceptor... interceptors)
在本例中执行到此步只有一个请求方法为games,ganmeController的handler
 添加拦截器.本例中未配置,为空  
     DispatcherServlet.getHandlerAdapter
返回适配的处理器
    返回适配的处理器
 遍历handlerAdapters    
     1. RequestMappingHandlerAdapter  
     2. HttpRequestHandlerAdapter  
     3. SimpleControllerHandlerAdapter  
     handlerAdapters.supports(handler)    
     supportsInternal(handler)  
     此处判断请求方式,如果是get请求...    
     AbstracthandlerAdaptersget.LastModified    
     getLastModifiedInternal : 总是返回-1  
     AbstractHandlerMethodAdapter.handle
使用HandlerAdapter来执行handler
到这里,我们执行完了方法,并获得了ModelAndView
此例中返回的是Null
    使用HandlerAdapter来执行handler
到这里,我们执行完了方法,并获得了ModelAndView
此例中返回的是Null
 RequestMappingHandlerAdapter.handleInternal    
     2. WebContentGenerator.checkAndPrepare (request, response, boolean lastModified) 
设置缓存,默认不会执行
    设置缓存,默认不会执行
 checkAndPrepare    
     applyCacheSeconds  
     invokeHandleMethod
返回ModelAndView
    返回ModelAndView
 创建一个ServletWebRequest  
     getDataBinderFactory
创建 WebDataBinderFactory
    创建 WebDataBinderFactory
 获取handler的类型,此处为GameController  
     判断是否初始化过  
     createDataBinderFactory    
     getWebBindingInitializer  
     new ServletRequestDataBinderFactory  
     getModelFactory
创建ModelFactory
    创建ModelFactory
 与getDataBinderFactory类似  
     createRequestMappingMethod
创建ServletInvocableHandlerMethod
    创建ServletInvocableHandlerMethod
 new 一个 ServletInvocableHandlerMethod    
     initResponseStatus
判断是否有responseStatus注解
    判断是否有responseStatus注解
 setHandlerMethodArgumentResolvers 等属性  
     new ModelAndViewContainer
创建ModelAndView容器
    创建ModelAndView容器
 modelFactory.initModel
初始化model
    初始化model
 invokeModelAttributeMethods
调用模型属性方法来填充模型。
  
    调用模型属性方法来填充模型。
 WebAsyncUtils.createAsyncWebRequest(request, response);
异步处理相关的处理
    异步处理相关的处理
 ServletInvocableHandlerMethod.invokeAndHandle
这里开始绑定参数和调用我们开发的方法
    这里开始绑定参数和调用我们开发的方法
 InvocableHandlerMethod.invokeForRequest
截止至此,我们调用了controller方法中并获得了方法的返回值
    
    截止至此,我们调用了controller方法中并获得了方法的返回值
在本例中就是Game类
     InvocableHandlerMethod.getMethodArgumentValues
获取当前请求的方法参数值。
获取到一个Object数组,里面分别存放着方法的参数:
Game,requst,response
    
    获取当前请求的方法参数值。
获取到一个Object数组,里面分别存放着方法的参数:
Game,requst,response
 getMethodParameters
调用handlerMethod的parameters参数
    
    调用handlerMethod的parameters参数
?????什么时候放进去的???????
 是一个MethodParameter类    
     MethodParameter是属于哪一个HandlerMthod类  
     method : 参数所在的方法  
     parameterType : 参数类型  
     遍历参数用于绑定  
     this.argumentResolvers.supportsParameter(parameter)
判断注册的方法是否支持指定的参数
从argumentResolver中获取
    判断注册的方法是否支持指定的参数
从argumentResolver中获取
  HandlerMethodArgumentResolverComposite.resolveArgument(parameter, mavContainer, request, this.dataBinderFactory);
参数解析,返回参数实例和值
本例中此处遍历三次,分别是Game,request,response
    参数解析,返回参数实例和值
本例中此处遍历三次,分别是Game,request,response
 getArgumentResolver(parameter)    
     从参数解析缓存中获取当前参数解析器,比如此例中的Game game  
     HandlerMethodArgumentResolver.resolveArgument(parameter, mavContainer, webRequest, binderFactory);
从模型中解析参数,如果没有找到,则使用它的默认值实例化它。并通过数据绑定将请求
值填充进模型,并可选地验证@Valid注解是否出现在参数上。
    从模型中解析参数,如果没有找到,则使用它的默认值实例化它。并通过数据绑定将请求
值填充进模型,并可选地验证@Valid注解是否出现在参数上。
截止至此,我们获得了一个绑定对象,目标类型为Game,参数名称为game,下面要为它赋值
 ModelFactory.getNameForParameter(parameter);  
     ModelFactory.getNameForParameter(parameter);
获取参数名称game
    获取参数名称game
 annot = parameter.getParameterAnnotation(ModelAttribute.class);
判断字段是否被ModelAttribute注解
  
    判断字段是否被ModelAttribute注解
 String attrName = (annot != null) ? annot.value() : null;
如果被注解则取注解的值,但若注解和形参同时存在则取注解的值
  
    如果被注解则取注解的值,但若注解和形参同时存在则取注解的值
 若未被注解则使用Conventions.getVariableNameForParameter取值    
     判断是否是数组  
     判断是否是集合,若是集合,但取值为Null则报错  
     否则直接取参数的类型  
     ClassUtils.getShortNameAsProperty
去除类型的完整包名,如com.jasmine.model.Game
    去除类型的完整包名,如com.jasmine.model.Game
 如果从mavContainner中能根据参数名称获取到属性,则直接取,否则先创建该属性再取
此处获取的Game对象,只不过此时它的变量都为null
    此处获取的Game对象,只不过此时它的变量都为null
 binderFactory.createBinder
开始将参数值绑定到对象中
    开始将参数值绑定到对象中
 ServletRequestDataBinderFactory.createBinderInstance(target, objectName, webRequest)
参数分别为Game对象,"game"字符串,request
最终会创建一个WebDataBinder对象,target为Game,名称为game
    参数分别为Game对象,"game"字符串,request
最终会创建一个WebDataBinder对象,target为Game,名称为game
 ExtendedServletRequestDataBinder.ExtendedServletRequestDataBinder(Game,game)
创建实例
ServletRequestDataBinder.ServletRequestDataBinder(target, objectName);
WebDataBinder.WebDataBinder(target, objectName);
DataBinder.DataBinder
这个会判断target参数是否是class java.util.Optional,如果不是就用绑定为原来的Game
  
    创建实例
ServletRequestDataBinder.ServletRequestDataBinder(target, objectName);
WebDataBinder.WebDataBinder(target, objectName);
DataBinder.DataBinder
这个会判断target参数是否是class java.util.Optional,如果不是就用绑定为原来的Game
 initBinder
初始化绑定器
    初始化绑定器
 set一些值  
     HandlerMethod    
     this.bean = handler; bean = controller
this.parameters = handlerMethod.parameters;
    this.parameters = handlerMethod.parameters;
 this.beanFactory = handlerMethod.beanFactory; 该bean的工厂
  
     this.beanType = handlerMethod.beanType; controller  
     this.method = handlerMethod.method; 请求路径对应的方法  
     this.bridgedMethod = handlerMethod.bridgedMethod;  
     ServletModelAttributeMethodProcessor.bindRequestParameters
绑定实参
到这里结束我们binder属性中
    
    绑定实参
到这里结束我们binder属性中
的target对象的gameId的值变为了1
     获取servletRequest  
     将绑定对象强转为ServletRequestDataBinder  
     ServletRequestDataBinder.bind(servletRequest)
开始绑定
    开始绑定
 根据request对象创建一个MutablePropertyValues
到这一步结束,我们获得一个MutablePropertyValues类
他包含我们的参数名称,参数值,用perpertyValues类的形式保存
    到这一步结束,我们获得一个MutablePropertyValues类
他包含我们的参数名称,参数值,用perpertyValues类的形式保存
name = gameId , value = 1
 ServletRequestParameterPropertyValues.ServletRequestParameterPropertyValues构造方法
    
     他会先调用WebUtils.getParametersStartingWith来获取一个Map对象
获取参数对应的值
    获取参数对应的值
 Enumeration<String> paramNames = request.getParameterNames()
获取参数枚举
    获取参数枚举
 创建一个treeMap用来保存参数  
     paramNames.nextElement() 
获取参数名gameId
  
    获取参数名gameId
 request.getParameterValues(paramName) 
根据参数名获取参数值
  
    根据参数名获取参数值
 将此参数放入到map中
此时map中包含数据
    此时map中包含数据
 key = gameId , value = 1  
     如果还有其他参数继续保存,否则返回这个map  
     MutablePropertyValues.MutablePropertyValues(Map original)
根据返回的map调用此类的构造方法
    
    根据返回的map调用此类的构造方法
 这个类其实是propertyValue的实现类,用于保存一些容易变动的配置参数  
     将map放入到名为propertyValueList的集合中  
     addBindValues(mpvs, request)
子类可用于为请求添加额外绑定值的扩展点。在doBind(MutablePropertyValues)之前调用。默认实现为空。
  
    子类可用于为请求添加额外绑定值的扩展点。在doBind(MutablePropertyValues)之前调用。默认实现为空。
 ServletRequestDataBinder.doBind(mpvs)
在实现绑定前要执行字段默认值和标记检查
    在实现绑定前要执行字段默认值和标记检查
 checkFieldDefaults
检查默认值,对于以某种特殊字符开头的值,如果不存在,则使用指定值
    检查默认值,对于以某种特殊字符开头的值,如果不存在,则使用指定值
 checkFieldMarkers
检查以字段标记前缀开头的字段。如果字段标记存在表明字段存在于表单中。
如果属性值不包含相应的字段值,则该字段将被视为空,并将被适当重置。
  
    检查以字段标记前缀开头的字段。如果字段标记存在表明字段存在于表单中。
如果属性值不包含相应的字段值,则该字段将被视为空,并将被适当重置。
 调用DataBinder.doBind    
     checkAllowedFields
删除不允许的字段值
    删除不允许的字段值
 PropertyAccessorUtils.canonicalPropertyName
移除字段旁边的单引号或双引号
{@code map['key']} -> {@code map[key]}
{@code map["key"]} -> {@code map[key]}
  
    移除字段旁边的单引号或双引号
{@code map['key']} -> {@code map[key]}
{@code map["key"]} -> {@code map[key]}
 checkRequiredFields
根据所需字段检查给定的属性值,在适当的地方生成缺失的字段错误。
  
    根据所需字段检查给定的属性值,在适当的地方生成缺失的字段错误。
 applyPropertyValues
将给定的属性值应用于目标对象。默认实现将所有提供的属性值应用为bean属性值。
    
    将给定的属性值应用于目标对象。默认实现将所有提供的属性值应用为bean属性值。
 AbstractPropertyAccessor.setPropertyValues    
     BeanWrapperImpl.setPropertyValue(PropertyValue pv)
执行到此,我们将值set到了实体Game中
    执行到此,我们将值set到了实体Game中
 获取参数名称
gameId
    gameId
 getBeanWrapperForPropertyPath(gameId);
对数据格式进行一些处理,详见此方法调用的
getFirstNestedPropertySeparatorIndex
并返回获取BeanWrapperImpl
它是一个bean的映射,其实就是Game类的映射
    对数据格式进行一些处理,详见此方法调用的
getFirstNestedPropertySeparatorIndex
并返回获取BeanWrapperImpl
它是一个bean的映射,其实就是Game类的映射
 getPropertyNameTokens
将属性名解析为一个属性名标记PropertyTokenHolder
    将属性名解析为一个属性名标记PropertyTokenHolder
 给PropertyValue的resolvedTokens属性赋值  
     setPropertyValue(PropertyTokenHolder tokens, PropertyValue pv)
935行的方法
    935行的方法
 PropertyDescriptor pd = PropertyValue.resolvedDescriptor;    
     PropertyDescriptor类:(属性描述器)
JDK java.beans包下的一个类
  
    JDK java.beans包下的一个类
 从pd中获取该参数的readMethod  
     执行readMethod.invoke(Game)获取旧值  
     convertForProperty
这里获得了根据类型转换后的参数的值 1
    这里获得了根据类型转换后的参数的值 1
 new 了一个property类  
     BeanWrapperImpl.convertIfNecessary    
     convertIfNecessary    
     TypeConverterDelegate.convertIfNecessary
将指定属性的值转换为所需类型
  
    将指定属性的值转换为所需类型
 writeMethod.invoke(this.object, value);
执行setGameId方法写入值
object = Game , value = 1;
    执行setGameId方法写入值
object = Game , value = 1;
 validateIfApplicable
检查方法是否有Validated注解
    检查方法是否有Validated注解
 将Modelset到mavContainer中  
     doInvoke
执行方法,获取返回值returnValue
    执行方法,获取返回值returnValue
 ReflectionUtils.makeAccessible(getBridgedMethod());
将方法设置为可执行
method.setAccessible(true);
  
    将方法设置为可执行
method.setAccessible(true);
 getBridgedMethod().invoke(getBean(), args);
调用此方法也就是我们的controller方法
  
    调用此方法也就是我们的controller方法
 setResponseStatus
如果有responseStatus注解则设置返回响应值
    如果有responseStatus注解则设置返回响应值
 this.returnValueHandlers.handleReturnValue    
     RequestResponseBodyMethodProcessor.handleReturnValue    
     writeWithMessageConverters
将给定的返回值写入给定的web请求
  
    将给定的返回值写入给定的web请求
 getModelAndView    
     mavContainer.isRequestHandled()
这里会判断是否完全处理,若为true,则返回Null
    这里会判断是否完全处理,若为true,则返回Null
 applyDefaultViewName  
     mappedHandler.applyPostHandle  
     processDispatchResult    
     triggerAfterCompletion  
     resetContextHolders  
     requestAttributes.requestCompleted()    
     executeRequestDestructionCallback
单独启动一个线程执行请求完成后已注册执行的所有回调。
  
    单独启动一个线程执行请求完成后已注册执行的所有回调。
 updateAccessedSessionAttributes  
     publishRequestHandledEvent  
     OncePerRequestFilter.doFilter  
    
 
 
 
 
  0 条评论
 下一页
  
   
   
   
   
  
  
  
  
  
  
  
  
  
  
 