说在前面

本次主要介绍springmvc配置解析。

springmvc配置解析

本次介绍MvcNamespaceHandler。

进入到这个方法org.springframework.web.servlet.config.ResourcesBeanDefinitionParser#parse

@Override
   public BeanDefinition parse(Element element, ParserContext context) {
      Object source = context.extractSource(element);
//    注册url服务处理器 ->
      registerUrlProvider(context, source);
//    注册路径匹配器bean定义 ->
      RuntimeBeanReference pathMatcherRef = MvcNamespaceUtils.registerPathMatcher(null, context, source);
//    注册url路径匹配器bean定义 ->
      RuntimeBeanReference pathHelperRef = MvcNamespaceUtils.registerUrlPathHelper(null, context, source);
//    注册resourceHandler ->
      String resourceHandlerName = registerResourceHandler(context, element, pathHelperRef, source);
      if (resourceHandlerName == null) {
         return null;
      }

      Map<String, String> urlMap = new ManagedMap<String, String>();
//    解析映射
      String resourceRequestPath = element.getAttribute("mapping");
      if (!StringUtils.hasText(resourceRequestPath)) {
         context.getReaderContext().error("The 'mapping' attribute is required.", context.extractSource(element));
         return null;
      }
      urlMap.put(resourceRequestPath, resourceHandlerName);
//    注册SimpleUrlHandlerMapping bean定义
      RootBeanDefinition handlerMappingDef = new RootBeanDefinition(SimpleUrlHandlerMapping.class);
      handlerMappingDef.setSource(source);
      handlerMappingDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
      handlerMappingDef.getPropertyValues().add("urlMap", urlMap);
      handlerMappingDef.getPropertyValues().add("pathMatcher", pathMatcherRef).add("urlPathHelper", pathHelperRef);
//    解析顺序属性
      String orderValue = element.getAttribute("order");
      // Use a default of near-lowest precedence, still allowing for even lower precedence in other mappings
      Object order = StringUtils.hasText(orderValue) ? orderValue : Ordered.LOWEST_PRECEDENCE - 1;
      handlerMappingDef.getPropertyValues().add("order", order);
//    注册跨域bean支持bean定义 ->
      RuntimeBeanReference corsRef = MvcNamespaceUtils.registerCorsConfigurations(null, context, source);
      handlerMappingDef.getPropertyValues().add("corsConfigurations", corsRef);
      String beanName = context.getReaderContext().generateBeanName(handlerMappingDef);
      context.getRegistry().registerBeanDefinition(beanName, handlerMappingDef);
      context.registerComponent(new BeanComponentDefinition(handlerMappingDef, beanName));
      // Ensure BeanNameUrlHandlerMapping (SPR-8289) and default HandlerAdapters are not "turned off"
      // Register HttpRequestHandlerAdapter 注册默认组件 ->
      MvcNamespaceUtils.registerDefaultComponents(context, source);
      return null;
   }

进入到这个方法org.springframework.web.servlet.config.ResourcesBeanDefinitionParser#registerUrlProvider

private void registerUrlProvider(ParserContext context, Object source) {
      if (!context.getRegistry().containsBeanDefinition(RESOURCE_URL_PROVIDER)) {
         RootBeanDefinition urlProvider = new RootBeanDefinition(ResourceUrlProvider.class);
         urlProvider.setSource(source);
         urlProvider.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
         context.getRegistry().registerBeanDefinition(RESOURCE_URL_PROVIDER, urlProvider);
//       注册mvcResourceUrlProvider bean定义
         context.registerComponent(new BeanComponentDefinition(urlProvider, RESOURCE_URL_PROVIDER));
//       注册ResourceUrlProviderExposingInterceptor bean定义
         RootBeanDefinition interceptor = new RootBeanDefinition(ResourceUrlProviderExposingInterceptor.class);
         interceptor.setSource(source);
         interceptor.getConstructorArgumentValues().addIndexedArgumentValue(0, urlProvider);
//       注册MappedInterceptor bean定义
         RootBeanDefinition mappedInterceptor = new RootBeanDefinition(MappedInterceptor.class);
         mappedInterceptor.setSource(source);
         mappedInterceptor.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
         mappedInterceptor.getConstructorArgumentValues().addIndexedArgumentValue(0, (Object) null);
         mappedInterceptor.getConstructorArgumentValues().addIndexedArgumentValue(1, interceptor);
         String mappedInterceptorName = context.getReaderContext().registerWithGeneratedName(mappedInterceptor);
         context.registerComponent(new BeanComponentDefinition(mappedInterceptor, mappedInterceptorName));
      }
   }

往上返回到这个方法org.springframework.web.servlet.config.MvcNamespaceUtils#registerPathMatcher

public static RuntimeBeanReference registerPathMatcher(
         RuntimeBeanReference pathMatcherRef, ParserContext parserContext, Object source) {

      if (pathMatcherRef != null) {
         if (parserContext.getRegistry().isAlias(PATH_MATCHER_BEAN_NAME)) {
            parserContext.getRegistry().removeAlias(PATH_MATCHER_BEAN_NAME);
         }
//       注册别名mvcPathMatcher
         parserContext.getRegistry().registerAlias(pathMatcherRef.getBeanName(), PATH_MATCHER_BEAN_NAME);
      }
      else if (!parserContext.getRegistry().isAlias(PATH_MATCHER_BEAN_NAME)
            && !parserContext.getRegistry().containsBeanDefinition(PATH_MATCHER_BEAN_NAME)) {
         RootBeanDefinition pathMatcherDef = new RootBeanDefinition(AntPathMatcher.class);
         pathMatcherDef.setSource(source);
         pathMatcherDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
//       注册mvcPathMatcher bean定义
         parserContext.getRegistry().registerBeanDefinition(PATH_MATCHER_BEAN_NAME, pathMatcherDef);
         parserContext.registerComponent(new BeanComponentDefinition(pathMatcherDef, PATH_MATCHER_BEAN_NAME));
      }
      return new RuntimeBeanReference(PATH_MATCHER_BEAN_NAME);
   }

往上返回到这个方法org.springframework.web.servlet.config.MvcNamespaceUtils#registerUrlPathHelper

public static RuntimeBeanReference registerUrlPathHelper(
         RuntimeBeanReference urlPathHelperRef, ParserContext parserContext, Object source) {

      if (urlPathHelperRef != null) {
         if (parserContext.getRegistry().isAlias(URL_PATH_HELPER_BEAN_NAME)) {
            parserContext.getRegistry().removeAlias(URL_PATH_HELPER_BEAN_NAME);
         }
//       注册mvcUrlPathHelper别名
         parserContext.getRegistry().registerAlias(urlPathHelperRef.getBeanName(), URL_PATH_HELPER_BEAN_NAME);
      }
      else if (!parserContext.getRegistry().isAlias(URL_PATH_HELPER_BEAN_NAME)
            && !parserContext.getRegistry().containsBeanDefinition(URL_PATH_HELPER_BEAN_NAME)) {
         RootBeanDefinition urlPathHelperDef = new RootBeanDefinition(UrlPathHelper.class);
         urlPathHelperDef.setSource(source);
         urlPathHelperDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
//       注册mvcUrlPathHelper bean定义
         parserContext.getRegistry().registerBeanDefinition(URL_PATH_HELPER_BEAN_NAME, urlPathHelperDef);
         parserContext.registerComponent(new BeanComponentDefinition(urlPathHelperDef, URL_PATH_HELPER_BEAN_NAME));
      }
      return new RuntimeBeanReference(URL_PATH_HELPER_BEAN_NAME);
   }

往上返回到这个方法org.springframework.web.servlet.config.ResourcesBeanDefinitionParser#registerResourceHandler

private String registerResourceHandler(
         ParserContext context, Element element, RuntimeBeanReference pathHelperRef, Object source) {

//    解析location属性值
      String locationAttr = element.getAttribute("location");
      if (!StringUtils.hasText(locationAttr)) {
         context.getReaderContext().error("The 'location' attribute is required.", context.extractSource(element));
         return null;
      }

//    注册ResourceHttpRequestHandler bean定义
      RootBeanDefinition resourceHandlerDef = new RootBeanDefinition(ResourceHttpRequestHandler.class);
      resourceHandlerDef.setSource(source);
      resourceHandlerDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
      MutablePropertyValues values = resourceHandlerDef.getPropertyValues();
//    解析url路径解析器
      values.add("urlPathHelper", pathHelperRef);
//    解析路径值
      values.add("locationValues", StringUtils.commaDelimitedListToStringArray(locationAttr));
//    获取缓存周期
      String cacheSeconds = element.getAttribute("cache-period");
      if (StringUtils.hasText(cacheSeconds)) {
         values.add("cacheSeconds", cacheSeconds);
      }

//    获取缓存配置
      Element cacheControlElement = DomUtils.getChildElementByTagName(element, "cache-control");
      if (cacheControlElement != null) {
//       解析缓存配置 ->
         CacheControl cacheControl = parseCacheControl(cacheControlElement);
         values.add("cacheControl", cacheControl);
      }

//    获取资源域属性
      Element resourceChainElement = DomUtils.getChildElementByTagName(element, "resource-chain");
      if (resourceChainElement != null) {
//       解析资源域 ->
         parseResourceChain(resourceHandlerDef, context, resourceChainElement, source);
      }

//    获取媒体类型管理器 ->
      Object manager = MvcNamespaceUtils.getContentNegotiationManager(context);
      if (manager != null) {
         values.add("contentNegotiationManager", manager);
      }

      String beanName = context.getReaderContext().generateBeanName(resourceHandlerDef);
      context.getRegistry().registerBeanDefinition(beanName, resourceHandlerDef);
      context.registerComponent(new BeanComponentDefinition(resourceHandlerDef, beanName));
      return beanName;
   }

进入到这个方法org.springframework.web.servlet.config.ResourcesBeanDefinitionParser#parseResourceChain

private void parseResourceChain(
         RootBeanDefinition resourceHandlerDef, ParserContext context, Element element, Object source) {

      String autoRegistration = element.getAttribute("auto-registration");
      boolean isAutoRegistration = !(StringUtils.hasText(autoRegistration) && "false".equals(autoRegistration));
      ManagedList<Object> resourceResolvers = new ManagedList<Object>();
      resourceResolvers.setSource(source);
      ManagedList<Object> resourceTransformers = new ManagedList<Object>();
      resourceTransformers.setSource(source);
//    解析资源缓存 ->
      parseResourceCache(resourceResolvers, resourceTransformers, element, source);
//    解析资源解析转换器
      parseResourceResolversTransformers(
            isAutoRegistration, resourceResolvers, resourceTransformers, context, element, source);
      if (!resourceResolvers.isEmpty()) {
         resourceHandlerDef.getPropertyValues().add("resourceResolvers", resourceResolvers);
      }
      if (!resourceTransformers.isEmpty()) {
         resourceHandlerDef.getPropertyValues().add("resourceTransformers", resourceTransformers);
      }
   }

进入到这个方法org.springframework.web.servlet.config.ResourcesBeanDefinitionParser#parseResourceCache

private void parseResourceCache(ManagedList<Object> resourceResolvers,
         ManagedList<Object> resourceTransformers, Element element, Object source) {

      String resourceCache = element.getAttribute("resource-cache");
      if ("true".equals(resourceCache)) {
         ConstructorArgumentValues cargs = new ConstructorArgumentValues();
//       注册CachingResourceResolver bean定义
         RootBeanDefinition cachingResolverDef = new RootBeanDefinition(CachingResourceResolver.class);
         cachingResolverDef.setSource(source);
         cachingResolverDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
         cachingResolverDef.setConstructorArgumentValues(cargs);
//       注册CachingResourceTransformer bean定义
         RootBeanDefinition cachingTransformerDef = new RootBeanDefinition(CachingResourceTransformer.class);
         cachingTransformerDef.setSource(source);
         cachingTransformerDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
         cachingTransformerDef.setConstructorArgumentValues(cargs);
//       获取缓存管理器配置
         String cacheManagerName = element.getAttribute("cache-manager");
         String cacheName = element.getAttribute("cache-name");
         if (StringUtils.hasText(cacheManagerName) && StringUtils.hasText(cacheName)) {
            RuntimeBeanReference cacheManagerRef = new RuntimeBeanReference(cacheManagerName);
            cargs.addIndexedArgumentValue(0, cacheManagerRef);
            cargs.addIndexedArgumentValue(1, cacheName);
         }
         else {
            ConstructorArgumentValues cacheCavs = new ConstructorArgumentValues();
            cacheCavs.addIndexedArgumentValue(0, RESOURCE_CHAIN_CACHE);
//          注册ConcurrentMapCache bean定义
            RootBeanDefinition cacheDef = new RootBeanDefinition(ConcurrentMapCache.class);
            cacheDef.setSource(source);
            cacheDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
            cacheDef.setConstructorArgumentValues(cacheCavs);
            cargs.addIndexedArgumentValue(0, cacheDef);
         }
         resourceResolvers.add(cachingResolverDef);
         resourceTransformers.add(cachingTransformerDef);
      }
   }

往上返回到这个方法org.springframework.web.servlet.config.MvcNamespaceUtils#getContentNegotiationManager

public static Object getContentNegotiationManager(ParserContext context) {
      String name = AnnotationDrivenBeanDefinitionParser.HANDLER_MAPPING_BEAN_NAME;
      if (context.getRegistry().containsBeanDefinition(name)) {
         BeanDefinition handlerMappingBeanDef = context.getRegistry().getBeanDefinition(name);
//       从RequestMappingHandlerMapping bean定义中获取
         return handlerMappingBeanDef.getPropertyValues().get("contentNegotiationManager");
      }
      name = AnnotationDrivenBeanDefinitionParser.CONTENT_NEGOTIATION_MANAGER_BEAN_NAME;
      if (context.getRegistry().containsBeanDefinition(name)) {
         return new RuntimeBeanReference(name);
      }
      return null;
   }

往上返回到这个方法org.springframework.web.servlet.config.MvcNamespaceUtils#registerCorsConfigurations

public static RuntimeBeanReference registerCorsConfigurations(
         Map<String, CorsConfiguration> corsConfigurations, ParserContext context, Object source) {

//    mvcCorsConfigurations 跨域支持bean定义解析
      if (!context.getRegistry().containsBeanDefinition(CORS_CONFIGURATION_BEAN_NAME)) {
         RootBeanDefinition corsDef = new RootBeanDefinition(LinkedHashMap.class);
         corsDef.setSource(source);
         corsDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
         if (corsConfigurations != null) {
            corsDef.getConstructorArgumentValues().addIndexedArgumentValue(0, corsConfigurations);
         }
//       注册mvcCorsConfigurations bean定义
         context.getReaderContext().getRegistry().registerBeanDefinition(CORS_CONFIGURATION_BEAN_NAME, corsDef);
         context.registerComponent(new BeanComponentDefinition(corsDef, CORS_CONFIGURATION_BEAN_NAME));
      }
      else if (corsConfigurations != null) {
         BeanDefinition corsDef = context.getRegistry().getBeanDefinition(CORS_CONFIGURATION_BEAN_NAME);
         corsDef.getConstructorArgumentValues().addIndexedArgumentValue(0, corsConfigurations);
      }
      return new RuntimeBeanReference(CORS_CONFIGURATION_BEAN_NAME);
   }

往上返回到这个方法org.springframework.web.servlet.config.MvcNamespaceUtils#registerDefaultComponents

public static void registerDefaultComponents(ParserContext parserContext, Object source) {
//    注册BeanNameUrlHandlerMapping bean定义 ->
      registerBeanNameUrlHandlerMapping(parserContext, source);
//    注册HttpRequestHandlerAdapter bean定义 ->
      registerHttpRequestHandlerAdapter(parserContext, source);
//    注册SimpleControllerHandlerAdapter bean定义 ->
      registerSimpleControllerHandlerAdapter(parserContext, source);
//    注册HandlerMappingIntrospector bean定义 ->
      registerHandlerMappingIntrospector(parserContext, source);
   }

这里前面解析过了。

往上返回到这个方法org.springframework.web.servlet.config.ResourcesBeanDefinitionParser#parse

说到最后

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

03-16 19:21