前言node
本文轉自「天河聊技術」微信公衆號spring
本次介紹ContextNamespaceHandler的property-placeholder、property-override節點微信
正文dom
先找到解析bean定義的地方ide
org.springframework.beans.factory.xml.DefaultBeanDefinitionDocumentReader#parseBeanDefinitionsui
protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) { // 根節點是不是命名空間 http://www.springframework.org/schema/beans if (delegate.isDefaultNamespace(root)) { NodeList nl = root.getChildNodes(); for (int i = 0; i < nl.getLength(); i++) { Node node = nl.item(i); if (node instanceof Element) { Element ele = (Element) node; if (delegate.isDefaultNamespace(ele)) { parseDefaultElement(ele, delegate); } else { delegate.parseCustomElement(ele); } } } } else { delegate.parseCustomElement(root); } }
@Nullable public BeanDefinition parseCustomElement(Element ele) { return parseCustomElement(ele, null); }
@Nullable public BeanDefinition parseCustomElement(Element ele, @Nullable BeanDefinition containingBd) { String namespaceUri = getNamespaceURI(ele); if (namespaceUri == null) { return null; } // 獲取解析命名空間的handler NamespaceHandler handler = this.readerContext.getNamespaceHandlerResolver().resolve(namespaceUri); if (handler == null) { error("Unable to locate Spring NamespaceHandler for XML schema namespace [" + namespaceUri + "]", ele); return null; } // handler解析 return handler.parse(ele, new ParserContext(this.readerContext, this, containingBd)); }
找到這行代碼this
// 獲取解析命名空間的handler NamespaceHandler handler = this.readerContext.getNamespaceHandlerResolver().resolve(namespaceUri);
進入這個方法spa
org.springframework.beans.factory.xml.DefaultNamespaceHandlerResolver#resolve這一行component
初始化namespaceHandler類 namespaceHandler.init();
進入這個方法server
org.springframework.context.config.ContextNamespaceHandler#init
@Override public void init() { registerBeanDefinitionParser("property-placeholder", new PropertyPlaceholderBeanDefinitionParser()); registerBeanDefinitionParser("property-override", new PropertyOverrideBeanDefinitionParser()); registerBeanDefinitionParser("annotation-config", new AnnotationConfigBeanDefinitionParser()); registerBeanDefinitionParser("component-scan", new ComponentScanBeanDefinitionParser()); registerBeanDefinitionParser("load-time-weaver", new LoadTimeWeaverBeanDefinitionParser()); registerBeanDefinitionParser("spring-configured", new SpringConfiguredBeanDefinitionParser()); registerBeanDefinitionParser("mbean-export", new MBeanExportBeanDefinitionParser()); registerBeanDefinitionParser("mbean-server", new MBeanServerBeanDefinitionParser()); }
返回到這個方法這一行
org.springframework.beans.factory.xml.BeanDefinitionParserDelegate#parseCustomElement(org.w3c.dom.Element, org.springframework.beans.factory.config.BeanDefinition)
// handler解析 return handler.parse(ele, new ParserContext(this.readerContext, this, containingBd));
進入這個方法
org.springframework.beans.factory.xml.NamespaceHandlerSupport#parse
@Override @Nullable public BeanDefinition parse(Element element, ParserContext parserContext) { // 得到bean定義解析器 BeanDefinitionParser parser = findParserForElement(element, parserContext); return (parser != null ? parser.parse(element, parserContext) : null); }
最後一行代碼
跟蹤到這個方法
org.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser#parseInternal這一行代碼
doParse(element, parserContext, builder);
進入這個方法
org.springframework.context.config.PropertyPlaceholderBeanDefinitionParser#doParse
@Override protected void doParse(Element element, ParserContext parserContext, BeanDefinitionBuilder builder) { super.doParse(element, parserContext, builder); builder.addPropertyValue("ignoreUnresolvablePlaceholders", Boolean.valueOf(element.getAttribute("ignore-unresolvable"))); String systemPropertiesModeName = element.getAttribute(SYSTEM_PROPERTIES_MODE_ATTRIBUTE); if (StringUtils.hasLength(systemPropertiesModeName) && !systemPropertiesModeName.equals(SYSTEM_PROPERTIES_MODE_DEFAULT)) { builder.addPropertyValue("systemPropertiesModeName", "SYSTEM_PROPERTIES_MODE_" + systemPropertiesModeName); } if (element.hasAttribute("value-separator")) { builder.addPropertyValue("valueSeparator", element.getAttribute("value-separator")); } if (element.hasAttribute("trim-values")) { builder.addPropertyValue("trimValues", element.getAttribute("trim-values")); } if (element.hasAttribute("null-value")) { builder.addPropertyValue("nullValue", element.getAttribute("null-value")); } }
第一行先調用了父類的方法
@Override protected void doParse(Element element, ParserContext parserContext, BeanDefinitionBuilder builder) { // 獲取location屬性 String location = element.getAttribute("location"); if (StringUtils.hasLength(location)) { // 獲得解析完佔位符的路徑 location = parserContext.getReaderContext().getEnvironment().resolvePlaceholders(location); // 路徑能夠是多個,按照,分開 String[] locations = StringUtils.commaDelimitedListToStringArray(location); builder.addPropertyValue("locations", locations); } String propertiesRef = element.getAttribute("properties-ref"); if (StringUtils.hasLength(propertiesRef)) { builder.addPropertyReference("properties", propertiesRef); } String fileEncoding = element.getAttribute("file-encoding"); if (StringUtils.hasLength(fileEncoding)) { builder.addPropertyValue("fileEncoding", fileEncoding); } String order = element.getAttribute("order"); if (StringUtils.hasLength(order)) { builder.addPropertyValue("order", Integer.valueOf(order)); } builder.addPropertyValue("ignoreResourceNotFound", Boolean.valueOf(element.getAttribute("ignore-resource-not-found"))); builder.addPropertyValue("localOverride", Boolean.valueOf(element.getAttribute("local-override"))); builder.setRole(BeanDefinition.ROLE_INFRASTRUCTURE); }
返回到這個方法
org.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser#doParse(org.w3c.dom.Element, org.springframework.beans.factory.xml.ParserContext, org.springframework.beans.factory.support.BeanDefinitionBuilder)
protected void doParse(Element element, ParserContext parserContext, BeanDefinitionBuilder builder) { doParse(element, builder); }
找到子類實現
org.springframework.context.config.PropertyOverrideBeanDefinitionParser#doParse
@Override protected void doParse(Element element, ParserContext parserContext, BeanDefinitionBuilder builder) { super.doParse(element, parserContext, builder); builder.addPropertyValue("ignoreInvalidKeys", Boolean.valueOf(element.getAttribute("ignore-unresolvable"))); }
先調用了父類的方法
最後
本次介紹到這裏,以上內容僅供參考。