說在前面web
本次主要介紹springmvc配置解析。spring
springmvc配置解析跨域
本次介紹MvcNamespaceHandler。緩存
進入到這個方法org.springframework.web.servlet.config.ResourcesBeanDefinitionParser#parsemvc
@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#registerUrlProviderapp
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#registerPathMatchercors
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#registerUrlPathHelperide
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#registerResourceHandlerui
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#parseResourceChainurl
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
說到最後
本次源碼解析僅表明我的觀點,僅供參考。