springmvc源码解析之@EnableWebMvc一

说在前面

本次介绍MvcNamespaceHandler。关注“天河聊架构”微信公众号更多源码解析。

 

springmvc配置解析

@EnableWebMvc这个注解干了什么,初始化RequestMappingHandlerMapping

先看下这个注解源码

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Documented
@Import(DelegatingWebMvcConfiguration.class)
public @interface EnableWebMvc {
}

直接找到这个类org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport

找到这个方法org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport#requestMappingHandlerMapping 初始化RequestMappingHandlerMapping

@Bean
   public RequestMappingHandlerMapping requestMappingHandlerMapping() {
//    创建RequestMappingHandlerMapping -》
      RequestMappingHandlerMapping mapping = createRequestMappingHandlerMapping();
      mapping.setOrder(0);
//    初始化拦截器 -》
      mapping.setInterceptors(getInterceptors());
//    设置媒体类型管理器 -》
      mapping.setContentNegotiationManager(mvcContentNegotiationManager());
//    跨域配置 -》
      mapping.setCorsConfigurations(getCorsConfigurations());
//    获取路径匹配配置器 -》
      PathMatchConfigurer configurer = getPathMatchConfigurer();
//    开启前缀匹配
      Boolean useSuffixPatternMatch = configurer.isUseSuffixPatternMatch();
      if (useSuffixPatternMatch != null) {
         mapping.setUseSuffixPatternMatch(useSuffixPatternMatch);
      }
      Boolean useRegisteredSuffixPatternMatch = configurer.isUseRegisteredSuffixPatternMatch();
      if (useRegisteredSuffixPatternMatch != null) {
         mapping.setUseRegisteredSuffixPatternMatch(useRegisteredSuffixPatternMatch);
      }
//    开启后缀匹配
      Boolean useTrailingSlashMatch = configurer.isUseTrailingSlashMatch();
      if (useTrailingSlashMatch != null) {
         mapping.setUseTrailingSlashMatch(useTrailingSlashMatch);
      }

//    获取url路径适配器
      UrlPathHelper pathHelper = configurer.getUrlPathHelper();
      if (pathHelper != null) {
         mapping.setUrlPathHelper(pathHelper);
      }
//    获取路径匹配器
      PathMatcher pathMatcher = configurer.getPathMatcher();
      if (pathMatcher != null) {
         mapping.setPathMatcher(pathMatcher);
      }

      return mapping;
   }

进入到这个方法org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping#afterPropertiesSet

@Override
   public void afterPropertiesSet() {
      this.config = new RequestMappingInfo.BuilderConfiguration();
//    设置url路径解析器
      this.config.setUrlPathHelper(getUrlPathHelper());
//    设置路径匹配器
      this.config.setPathMatcher(getPathMatcher());
//    设置前缀路径匹配器
      this.config.setSuffixPatternMatch(this.useSuffixPatternMatch);
//    设置后缀路径匹配器
      this.config.setTrailingSlashMatch(this.useTrailingSlashMatch);
//    注册路径前缀匹配器
      this.config.setRegisteredSuffixPatternMatch(this.useRegisteredSuffixPatternMatch);
//    设置媒体类型管理器
      this.config.setContentNegotiationManager(getContentNegotiationManager());
//-》
      super.afterPropertiesSet();
   }

进入到这个方法org.springframework.web.servlet.handler.AbstractHandlerMethodMapping#initHandlerMethods

protected void initHandlerMethods() {
      if (logger.isDebugEnabled()) {
         logger.debug("Looking for request mappings in application context: " + getApplicationContext());
      }
      String[] beanNames = (this.detectHandlerMethodsInAncestorContexts ?
            BeanFactoryUtils.beanNamesForTypeIncludingAncestors(getApplicationContext(), Object.class) :
            getApplicationContext().getBeanNamesForType(Object.class));
      for (String beanName : beanNames) {
         if (!beanName.startsWith(SCOPED_TARGET_NAME_PREFIX)) {
            Class<?> beanType = null;
            try {
               beanType = getApplicationContext().getType(beanName);
            }
            catch (Throwable ex) {
               // An unresolvable bean type, probably from a lazy bean - let's ignore it.
               if (logger.isDebugEnabled()) {
                  logger.debug("Could not resolve target class for bean with name '" + beanName + "'", ex);
               }
            }
            if (beanType != null && isHandler(beanType)) {
               detectHandlerMethods(beanName);
            }
         }
      }
//    获取handlerMethod并初始化
      handlerMethodsInitialized(getHandlerMethods());
   }

往上返回到这个方法org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport#getInterceptors

protected final Object[] getInterceptors() {
      if (this.interceptors == null) {
//       创建拦截器注册器
         InterceptorRegistry registry = new InterceptorRegistry();
//       mvc配置器添加拦截器注册器 -》
         addInterceptors(registry);
//       添加ConversionServiceExposingInterceptor 拦截器 -》
         registry.addInterceptor(new ConversionServiceExposingInterceptor(mvcConversionService()));
//       添加ResourceUrlProviderExposingInterceptor 拦截器 -》
         registry.addInterceptor(new ResourceUrlProviderExposingInterceptor(mvcResourceUrlProvider()));
//       从拦截器注册器中获取拦截器 -》
         this.interceptors = registry.getInterceptors();
      }
      return this.interceptors.toArray();
   }

进入到这个方法org.springframework.web.servlet.config.annotation.DelegatingWebMvcConfiguration#addInterceptors

@Override
protected void addInterceptors(InterceptorRegistry registry) {
   this.configurers.addInterceptors(registry);
}

进入到这个方法org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport#mvcConversionService

@Bean
   public FormattingConversionService mvcConversionService() {
//    初始化默认转换服务
      FormattingConversionService conversionService = new DefaultFormattingConversionService();
//    添加格式化器 -》
      addFormatters(conversionService);
      return conversionService;
   }

进入到这个方法org.springframework.web.servlet.config.annotation.DelegatingWebMvcConfiguration#addFormatters

@Override
protected void addFormatters(FormatterRegistry registry) {
   this.configurers.addFormatters(registry);
}

往上返回到这个方法org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport#mvcResourceUrlProvider

@Bean
   public ResourceUrlProvider mvcResourceUrlProvider() {
//    初始化资源url服务器
      ResourceUrlProvider urlProvider = new ResourceUrlProvider();
//    获取url路径解析器 -》
      UrlPathHelper pathHelper = getPathMatchConfigurer().getUrlPathHelper();
      if (pathHelper != null) {
         urlProvider.setUrlPathHelper(pathHelper);
      }
      PathMatcher pathMatcher = getPathMatchConfigurer().getPathMatcher();
      if (pathMatcher != null) {
         urlProvider.setPathMatcher(pathMatcher);
      }
      return urlProvider;
   }

进入到这个方法org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport#getPathMatchConfigurer

protected PathMatchConfigurer getPathMatchConfigurer() {
   if (this.pathMatchConfigurer == null) {
      this.pathMatchConfigurer = new PathMatchConfigurer();
      configurePathMatch(this.pathMatchConfigurer);
   }
   return this.pathMatchConfigurer;
}

进入到这个方法org.springframework.web.servlet.config.annotation.DelegatingWebMvcConfiguration#configurePathMatch

@Override
protected void configurePathMatch(PathMatchConfigurer configurer) {
   this.configurers.configurePathMatch(configurer);
}

往上返回到这个方法org.springframework.web.servlet.config.annotation.InterceptorRegistry#getInterceptors

protected List<Object> getInterceptors() {
      List<Object> interceptors = new ArrayList<Object>(this.registrations.size());
      for (InterceptorRegistration registration : this.registrations) {
//       获取拦截器 -》
         interceptors.add(registration.getInterceptor());
      }
      return interceptors ;
   }

进入到这个方法org.springframework.web.servlet.config.annotation.InterceptorRegistration#getInterceptor

protected Object getInterceptor() {
      if (this.includePatterns.isEmpty() && this.excludePatterns.isEmpty()) {
         return this.interceptor;
      }

//    解析包含路径
      String[] include = StringUtils.toStringArray(this.includePatterns);
//    解析排除路径
      String[] exclude = StringUtils.toStringArray(this.excludePatterns);
      MappedInterceptor mappedInterceptor = new MappedInterceptor(include, exclude, this.interceptor);
      if (this.pathMatcher != null) {
         mappedInterceptor.setPathMatcher(this.pathMatcher);
      }
      return mappedInterceptor;
   }

往上返回到这个方法org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport#mvcContentNegotiationManager

进入到这个方法org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport#getDefaultMediaTypes

protected Map<String, MediaType> getDefaultMediaTypes() {
   Map<String, MediaType> map = new HashMap<String, MediaType>(4);
   if (romePresent) {
      map.put("atom", MediaType.APPLICATION_ATOM_XML);
      map.put("rss", MediaType.APPLICATION_RSS_XML);
   }
   if (jaxb2Present || jackson2XmlPresent) {
      map.put("xml", MediaType.APPLICATION_XML);
   }
   if (jackson2Present || gsonPresent) {
      map.put("json", MediaType.APPLICATION_JSON);
   }
   return map;
}

往上返回到这个方法org.springframework.web.servlet.config.annotation.DelegatingWebMvcConfiguration#configureContentNegotiation

@Override
protected void configureContentNegotiation(ContentNegotiationConfigurer configurer) {
   this.configurers.configureContentNegotiation(configurer);
}

往上返回到这个方法org.springframework.web.servlet.config.annotation.ContentNegotiationConfigurer#buildContentNegotiationManager

protected ContentNegotiationManager buildContentNegotiationManager() {
//    添加媒体类型
      this.factory.addMediaTypes(this.mediaTypes);
//    等待ContentNegotiationManagerFactoryBean初始化配置
      this.factory.afterPropertiesSet();
      return this.factory.getObject();
   }

往上返回到这个方法org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport#getCorsConfigurations

protected final Map<String, CorsConfiguration> getCorsConfigurations() {
      if (this.corsConfigurations == null) {
//       初始化跨域注册器
         CorsRegistry registry = new CorsRegistry();
//       添加跨域映射 -》
         addCorsMappings(registry);
//       获取跨域配置 -》
         this.corsConfigurations = registry.getCorsConfigurations();
      }
      return this.corsConfigurations;
   }

进入到这个方法org.springframework.web.servlet.config.annotation.DelegatingWebMvcConfiguration#addCorsMappings

@Override
protected void addCorsMappings(CorsRegistry registry) {
   this.configurers.addCorsMappings(registry);
}

进入到这个方法org.springframework.web.servlet.config.annotation.CorsRegistry#getCorsConfigurations

protected Map<String, CorsConfiguration> getCorsConfigurations() {
   Map<String, CorsConfiguration> configs = new LinkedHashMap<String, CorsConfiguration>(this.registrations.size());
   for (CorsRegistration registration : this.registrations) {
      configs.put(registration.getPathPattern(), registration.getCorsConfiguration());
   }
   return configs;
}

往上返回到这个方法org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport#getPathMatchConfigurer

protected PathMatchConfigurer getPathMatchConfigurer() {
   if (this.pathMatchConfigurer == null) {
      this.pathMatchConfigurer = new PathMatchConfigurer();
      configurePathMatch(this.pathMatchConfigurer);
   }
   return this.pathMatchConfigurer;
}

进入到这个方法org.springframework.web.servlet.config.annotation.DelegatingWebMvcConfiguration#configurePathMatch

@Override
protected void configurePathMatch(PathMatchConfigurer configurer) {
   this.configurers.configurePathMatch(configurer);
}

往上返回到这个方法org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport#requestMappingHandlerMapping

 

说到最后

本次源码解析仅代表个人观点,仅供参考。

 

转载于:https://my.oschina.net/u/3775437/blog/3024926

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值