说在前面
本次主要介绍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
说到最后
本次源码解析仅代表个人观点,仅供参考。