springmvc源码 - handlerAdapter是如何初始化的

Source

其实在之前的笔记中,有记录过handlerAdapter、handlerMapping初始化的一些细节,但是前几天在写策略模式那篇笔记的时候,突然间想到一个问题,RequestMappingHandlerAdapter、RequestMappingHandlerMapping是在什么时候放入到beanDefinitionMap中的

今天这篇笔记主要记录下这里是如何放入到beanDefinitionMap中这个问题

其实这篇笔记也可以理解为springboot项目和传统的springmvc项目有什么区别

结论

简单来说:在EnableWebMvcConfiguration中,通过@Bean来完成的

@Configuration
public static class EnableWebMvcConfiguration extends DelegatingWebMvcConfiguration {
    
      

  private final WebMvcProperties mvcProperties;

  private final ListableBeanFactory beanFactory;

  private final WebMvcRegistrations mvcRegistrations;

  public EnableWebMvcConfiguration(
      ObjectProvider<WebMvcProperties> mvcPropertiesProvider,
      ObjectProvider<WebMvcRegistrations> mvcRegistrationsProvider,
      ListableBeanFactory beanFactory) {
    
      
    this.mvcProperties = mvcPropertiesProvider.getIfAvailable();
    this.mvcRegistrations = mvcRegistrationsProvider.getIfUnique();
    this.beanFactory = beanFactory;
  }

  @Bean
  @Override
  public RequestMappingHandlerAdapter requestMappingHandlerAdapter() {
    
      
    RequestMappingHandlerAdapter adapter = super.requestMappingHandlerAdapter();
    adapter.setIgnoreDefaultModelOnRedirect(this.mvcProperties != null
        ? this.mvcProperties.isIgnoreDefaultModelOnRedirect() : true);
    return adapter;
  }

  @Override
  protected RequestMappingHandlerAdapter createRequestMappingHandlerAdapter() {
    
      
    if (this.mvcRegistrations != null
        && this.mvcRegistrations.getRequestMappingHandlerAdapter() != null) {
    
      
      return this.mvcRegistrations.getRequestMappingHandlerAdapter();
    }
    return super.createRequestMappingHandlerAdapter();
  }

  @Bean
  @Primary
  @Override
  public RequestMappingHandlerMapping requestMappingHandlerMapping() {
    
      
    // Must be @Primary for MvcUriComponentsBuilder to work
    return super.requestMappingHandlerMapping();
  }


  @Override
  protected RequestMappingHandlerMapping createRequestMappingHandlerMapping() {
    
      
    if (this.mvcRegistrations != null
        && this.mvcRegistrations.getRequestMappingHandlerMapping() != null) {
    
      
      return this.mvcRegistrations.getRequestMappingHandlerMapping();
    }
    return super.createRequestMappingHandlerMapping();
  }
}

这里我删减了部分代码,可以看到,在这个类中,通过@Bean声明了handlerMapping和handlerAdapter,这是对于springboot项目来说的

那EnableWebMvcConfiguration是在什么时候被初始化的?或者说是如何被spring所扫描到的?我们实际在代码中会发现,EnableMvcConfiguration是WebMvcAutoConfiguration的一个内部类,而WebMvcAutoConfiguration是通过springboot的自动配置来完成的,在springboot-autoconfigure.jar包的spring.factories文件中有配置该bean

springmvc项目是如何初始化handlerMapping的?

那非springboot项目呢?如果我的项目就是一个传统的springmvc项目,非springboot项目,没有自动注入的功能,那怎么办?其实很简单,既然传统的springmvc项目没有自动注入,那我程序员就自己去注入,通过@EnableWebMvc这个注解;

@EnableWebMvc注解通过@Import引入了一个类DelegatingWebMvcConfiguration
在DelegatingWebMvcConfiguration中,并没有对handlerMapping的处理,但是在其父类中:WebMvcConfigurationSupport
通过@Bean去定义了handlerMapping和handlerAdapter,所以,对于springmvc项目来说,也是通过@Bean这种形式来声明handlerMapping的,只是和springboot项目相比,时机不同而已,但是底层的原理都是一样的

其实说到这个点,最近有一个反思,学习一个框架,先要学习底层的思想,而上层的框架,无非就是在底层的扩展点上翻来覆去的使用,spring、springboot、springmvc这三个框架,在看源码的时候,深有体会;也就是说,在看springboot的源码的时候,需要先了解spring底层的源码,因为在springboot中,很多很多点,都是通过spring底层的一个扩展点或者是底层逻辑来实现的,那这样,在看springboot源码的时候,就能比较快的连贯起来,否则的话,那我们想下,看到springboot的一个点,去学习下spring的原理,那这样的话,等学会了spring这个点的原理,再反过来去看springboot的时候,就可能连贯不起来了

通过@Bean,声明了handlerMapping和handlerAdapter之后,那其他的事情,就不需要springmvc去处理了,spring底层会帮我们去初始化、实例化等等

所以,spring源码看的多了,就会发现,底层的一些思想,真的是很值得去学习的,不知道该怎么去表达,总之,源码在看起来是比较难得,但是越往后学习,源码学起来越快,因为前面说了,思想是基本上一样的

说到这里了,再扯点其他的,在没有看spring官方文档之前,或者说从上大学开始,对于spring、springmvc我一直认为是两个项目,或者说我认为springmvc是在spring基础之上的一个提升
但是,实际去看下官方文档,springmvc只是spring的一部分,我们通常所说的spring,就是spring framework,而在官方文档中,springmvc只是spring framework的一个章节
在这里插入图片描述
至于我们常说的IOC、AOP、el表达式,是spring framework中的core这个章节的一部分