前言java
本文轉自「天河聊技術」微信公衆號node
此次介紹UtilNamespaceHandlerspring
正文微信
找到這個方法app
org.springframework.beans.factory.xml.DefaultBeanDefinitionDocumentReader#parseBeanDefinitionsdom
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); } }
找到這行代碼ide
else { delegate.parseCustomElement(ele); }
@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)); }
找到這行代碼post
// 獲取解析命名空間的handler NamespaceHandler handler = this.readerContext.getNamespaceHandlerResolver().resolve(namespaceUri);
@Override @Nullable public NamespaceHandler resolve(String namespaceUri) { // 獲取handlerMappings,從META-INF/spring.handlers這個路徑加載 Map<String, Object> handlerMappings = getHandlerMappings(); Object handlerOrClassName = handlerMappings.get(namespaceUri); if (handlerOrClassName == null) { return null; } else if (handlerOrClassName instanceof NamespaceHandler) { return (NamespaceHandler) handlerOrClassName; } else { String className = (String) handlerOrClassName; try { Class<?> handlerClass = ClassUtils.forName(className, this.classLoader); // handler必須是這個類型 NamespaceHandler if (!NamespaceHandler.class.isAssignableFrom(handlerClass)) { throw new FatalBeanException("Class [" + className + "] for namespace [" + namespaceUri + "] does not implement the [" + NamespaceHandler.class.getName() + "] interface"); } // 建立namespaceHandler類 NamespaceHandler namespaceHandler = (NamespaceHandler) BeanUtils.instantiateClass(handlerClass); // 初始化namespaceHandler類 namespaceHandler.init(); handlerMappings.put(namespaceUri, namespaceHandler); return namespaceHandler; } catch (ClassNotFoundException ex) { throw new FatalBeanException("Could not find NamespaceHandler class [" + className + "] for namespace [" + namespaceUri + "]", ex); } catch (LinkageError err) { throw new FatalBeanException("Unresolvable class definition for NamespaceHandler class [" + className + "] for namespace [" + namespaceUri + "]", err); } } }
進入這個方法org.springframework.beans.factory.xml.UtilNamespaceHandler#initui
@Override public void init() { registerBeanDefinitionParser("constant", new ConstantBeanDefinitionParser()); registerBeanDefinitionParser("property-path", new PropertyPathBeanDefinitionParser()); registerBeanDefinitionParser("list", new ListBeanDefinitionParser()); registerBeanDefinitionParser("set", new SetBeanDefinitionParser()); registerBeanDefinitionParser("map", new MapBeanDefinitionParser()); registerBeanDefinitionParser("properties", new PropertiesBeanDefinitionParser()); }
返回到這個方法org.springframework.beans.factory.xml.BeanDefinitionParserDelegate#parseCustomElement(org.w3c.dom.Element, org.springframework.beans.factory.config.BeanDefinition)這一行代碼進行handler解析this
// handler解析 return handler.parse(ele, new ParserContext(this.readerContext, this, containingBd));
進入這個方法
@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.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.AbstractBeanDefinitionParser#parse
@Override @Nullable public final BeanDefinition parse(Element element, ParserContext parserContext) { // 解析bean定義的模板方法 AbstractBeanDefinition definition = parseInternal(element, parserContext); if (definition != null && !parserContext.isNested()) { try { // 解析id屬性 String id = resolveId(element, definition, parserContext); if (!StringUtils.hasText(id)) { parserContext.getReaderContext().error( "Id is required for element '" + parserContext.getDelegate().getLocalName(element) + "' when used as a top-level tag", element); } String[] aliases = null; if (shouldParseNameAsAliases()) { // 解析name屬性 String name = element.getAttribute(NAME_ATTRIBUTE); if (StringUtils.hasLength(name)) { aliases = StringUtils.trimArrayElements(StringUtils.commaDelimitedListToStringArray(name)); } } BeanDefinitionHolder holder = new BeanDefinitionHolder(definition, id, aliases); registerBeanDefinition(holder, parserContext.getRegistry()); if (shouldFireEvents()) { BeanComponentDefinition componentDefinition = new BeanComponentDefinition(holder); postProcessComponentDefinition(componentDefinition); parserContext.registerComponent(componentDefinition); } } catch (BeanDefinitionStoreException ex) { String msg = ex.getMessage(); parserContext.getReaderContext().error((msg != null ? msg : ex.toString()), element); return null; } } return definition; }
找到這一行代碼
// 解析bean定義的模板方法 AbstractBeanDefinition definition = parseInternal(element, parserContext);
@Override protected final AbstractBeanDefinition parseInternal(Element element, ParserContext parserContext) { BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(); String parentName = getParentName(element); if (parentName != null) { } builder.getRawBeanDefinition().setParentName(parentName); Class<?> beanClass = getBeanClass(element); if (beanClass != null) { builder.getRawBeanDefinition().setBeanClass(beanClass); } else { String beanClassName = getBeanClassName(element); if (beanClassName != null) { builder.getRawBeanDefinition().setBeanClassName(beanClassName); } } builder.getRawBeanDefinition().setSource(parserContext.extractSource(element)); // 獲取內部bean的bean定義 BeanDefinition containingBd = parserContext.getContainingBeanDefinition(); // 若是匿名bean有scope,外部bean的scope以這個爲主 if (containingBd != null) { // Inner bean definition must receive same scope as containing bean. builder.setScope(containingBd.getScope()); } // 是否延遲加載 if (parserContext.isDefaultLazyInit()) { // Default-lazy-init applies to custom bean definitions as well. builder.setLazyInit(true); } doParse(element, parserContext, builder); return builder.getBeanDefinition(); }
進入這個方法
// 調用此方法時會具體調用子類重寫的方法,如org.springframework.beans.factory.xml.UtilNamespaceHandler.ListBeanDefinitionParser.doParse() protected void doParse(Element element, ParserContext parserContext, BeanDefinitionBuilder builder) { doParse(element, builder); }
找到上面的實現方法
org.springframework.beans.factory.xml.UtilNamespaceHandler.ListBeanDefinitionParser#doParse list節點解析
@Override protected void doParse(Element element, ParserContext parserContext, BeanDefinitionBuilder builder) { List<Object> parsedList = parserContext.getDelegate().parseListElement(element, builder.getRawBeanDefinition()); builder.addPropertyValue("sourceList", parsedList); String listClass = element.getAttribute("list-class"); if (StringUtils.hasText(listClass)) { builder.addPropertyValue("targetListClass", listClass); } // 獲取scope屬性值 String scope = element.getAttribute(SCOPE_ATTRIBUTE); if (StringUtils.hasLength(scope)) { builder.setScope(scope); } } }
public List<Object> parseListElement(Element collectionEle, @Nullable BeanDefinition bd) { // value-type標籤 String defaultElementType = collectionEle.getAttribute(VALUE_TYPE_ATTRIBUTE); NodeList nl = collectionEle.getChildNodes(); ManagedList<Object> target = new ManagedList<>(nl.getLength()); target.setSource(extractSource(collectionEle)); target.setElementTypeName(defaultElementType); target.setMergeEnabled(parseMergeAttribute(collectionEle)); parseCollectionElements(nl, target, bd, defaultElementType); return target; }
public boolean parseMergeAttribute(Element collectionElement) { // merge屬性 String value = collectionElement.getAttribute(MERGE_ATTRIBUTE); // 若是是default則以beans的配置爲主 if (DEFAULT_VALUE.equals(value)) { value = this.defaults.getMerge(); } return TRUE_VALUE.equals(value); }
protected void parseCollectionElements( NodeList elementNodes, Collection<Object> target, @Nullable BeanDefinition bd, String defaultElementType) { for (int i = 0; i < elementNodes.getLength(); i++) { Node node = elementNodes.item(i); // description 解析屬性 if (node instanceof Element && !nodeNameEquals(node, DESCRIPTION_ELEMENT)) { // 遞歸調用 target.add(parsePropertySubElement((Element) node, bd, defaultElementType)); } } }
進入這個方法
org.springframework.beans.factory.xml.BeanDefinitionParserDelegate#parsePropertySubElement(org.w3c.dom.Element, org.springframework.beans.factory.config.BeanDefinition, java.lang.String)
@Nullable public Object parsePropertySubElement(Element ele, @Nullable BeanDefinition bd, @Nullable String defaultValueType) { // 若是不是beans節點 if (!isDefaultNamespace(ele)) { return parseNestedCustomElement(ele, bd); } // 解析bean節點 else if (nodeNameEquals(ele, BEAN_ELEMENT)) { // 解析<bean>節點的bean定義 BeanDefinitionHolder nestedBd = parseBeanDefinitionElement(ele, bd); if (nestedBd != null) { // 解析內部的required的元素 nestedBd = decorateBeanDefinitionIfRequired(ele, nestedBd, bd); } return nestedBd; } // ref屬性指定的節點 else if (nodeNameEquals(ele, REF_ELEMENT)) { // A generic reference to any name of any bean. // 獲取bean屬性值 String refName = ele.getAttribute(BEAN_REF_ATTRIBUTE); boolean toParent = false; if (!StringUtils.hasLength(refName)) { // A reference to the id of another bean in a parent context.parent屬性值獲取另外一個bean的引用 refName = ele.getAttribute(PARENT_REF_ATTRIBUTE); toParent = true; if (!StringUtils.hasLength(refName)) { error("'bean' or 'parent' is required for <ref> element", ele); return null; } } if (!StringUtils.hasText(refName)) { error("<ref> element contains empty target attribute", ele); return null; } RuntimeBeanReference ref = new RuntimeBeanReference(refName, toParent); ref.setSource(extractSource(ele)); return ref; } // 解析idref屬性,注入的是bean的id而不是bean的實例 else if (nodeNameEquals(ele, IDREF_ELEMENT)) { return parseIdRefElement(ele); } // 若是是value節點 else if (nodeNameEquals(ele, VALUE_ELEMENT)) { return parseValueElement(ele, defaultValueType); } // 若是是null節點 else if (nodeNameEquals(ele, NULL_ELEMENT)) { // It's a distinguished null value. Let's wrap it in a TypedStringValue // object in order to preserve the source location. TypedStringValue nullHolder = new TypedStringValue(null); nullHolder.setSource(extractSource(ele)); return nullHolder; } // 若是是array節點 else if (nodeNameEquals(ele, ARRAY_ELEMENT)) { return parseArrayElement(ele, bd); } // 若是是list節點 else if (nodeNameEquals(ele, LIST_ELEMENT)) { return parseListElement(ele, bd); } // 若是是set節點 else if (nodeNameEquals(ele, SET_ELEMENT)) { return parseSetElement(ele, bd); } // 若是是map節點 else if (nodeNameEquals(ele, MAP_ELEMENT)) { return parseMapElement(ele, bd); } // 若是是props節點 else if (nodeNameEquals(ele, PROPS_ELEMENT)) { return parsePropsElement(ele); } else { error("Unknown property sub-element: [" + ele.getNodeName() + "]", ele); return null; } }
找到這行代碼
// 解析idref屬性,注入的是bean的id而不是bean的實例 else if (nodeNameEquals(ele, IDREF_ELEMENT)) { return parseIdRefElement(ele); }
@Nullable public Object parseIdRefElement(Element ele) { // A generic reference to any name of any bean.獲取bean屬性值 String refName = ele.getAttribute(BEAN_REF_ATTRIBUTE); if (!StringUtils.hasLength(refName)) { error("'bean' is required for <idref> element", ele); return null; } if (!StringUtils.hasText(refName)) { error("<idref> element contains empty target attribute", ele); return null; } RuntimeBeanNameReference ref = new RuntimeBeanNameReference(refName); ref.setSource(extractSource(ele)); return ref; }
找到這行代碼
// 若是是value節點 else if (nodeNameEquals(ele, VALUE_ELEMENT)) { return parseValueElement(ele, defaultValueType); }
public Object parseValueElement(Element ele, @Nullable String defaultTypeName) { // It's a literal value. String value = DomUtils.getTextValue(ele); // 獲取type屬性值 String specifiedTypeName = ele.getAttribute(TYPE_ATTRIBUTE); String typeName = specifiedTypeName; if (!StringUtils.hasText(typeName)) { typeName = defaultTypeName; } try { TypedStringValue typedValue = buildTypedStringValue(value, typeName); typedValue.setSource(extractSource(ele)); typedValue.setSpecifiedTypeName(specifiedTypeName); return typedValue; } catch (ClassNotFoundException ex) { error("Type class [" + typeName + "] not found for <value> element", ele, ex); return value; } }
找到這行代碼
// 若是是array節點 else if (nodeNameEquals(ele, ARRAY_ELEMENT)) { return parseArrayElement(ele, bd); }
public Object parseArrayElement(Element arrayEle, @Nullable BeanDefinition bd) { // 獲取value-type屬性值 String elementType = arrayEle.getAttribute(VALUE_TYPE_ATTRIBUTE); NodeList nl = arrayEle.getChildNodes(); ManagedArray target = new ManagedArray(elementType, nl.getLength()); target.setSource(extractSource(arrayEle)); target.setElementTypeName(elementType); target.setMergeEnabled(parseMergeAttribute(arrayEle)); parseCollectionElements(nl, target, bd, elementType); return target; }
public boolean parseMergeAttribute(Element collectionElement) { // merge屬性 String value = collectionElement.getAttribute(MERGE_ATTRIBUTE); // 若是是default則以beans的配置爲主 if (DEFAULT_VALUE.equals(value)) { value = this.defaults.getMerge(); } return TRUE_VALUE.equals(value); }
protected void parseCollectionElements( NodeList elementNodes, Collection<Object> target, @Nullable BeanDefinition bd, String defaultElementType) { for (int i = 0; i < elementNodes.getLength(); i++) { Node node = elementNodes.item(i); // description 解析屬性 if (node instanceof Element && !nodeNameEquals(node, DESCRIPTION_ELEMENT)) { // 遞歸調用 target.add(parsePropertySubElement((Element) node, bd, defaultElementType)); } } }
找到這行代碼
// 若是是list節點 else if (nodeNameEquals(ele, LIST_ELEMENT)) { return parseListElement(ele, bd); }
public List<Object> parseListElement(Element collectionEle, @Nullable BeanDefinition bd) { // value-type標籤 String defaultElementType = collectionEle.getAttribute(VALUE_TYPE_ATTRIBUTE); NodeList nl = collectionEle.getChildNodes(); ManagedList<Object> target = new ManagedList<>(nl.getLength()); target.setSource(extractSource(collectionEle)); target.setElementTypeName(defaultElementType); target.setMergeEnabled(parseMergeAttribute(collectionEle)); parseCollectionElements(nl, target, bd, defaultElementType); return target; }
找到這行代碼
// 若是是set節點 else if (nodeNameEquals(ele, SET_ELEMENT)) { return parseSetElement(ele, bd); }
public Set<Object> parseSetElement(Element collectionEle, @Nullable BeanDefinition bd) { // 獲取value-type屬性值 String defaultElementType = collectionEle.getAttribute(VALUE_TYPE_ATTRIBUTE); NodeList nl = collectionEle.getChildNodes(); ManagedSet<Object> target = new ManagedSet<>(nl.getLength()); target.setSource(extractSource(collectionEle)); target.setElementTypeName(defaultElementType); target.setMergeEnabled(parseMergeAttribute(collectionEle)); parseCollectionElements(nl, target, bd, defaultElementType); return target; }
找到這行代碼
// 若是是map節點 else if (nodeNameEquals(ele, MAP_ELEMENT)) { return parseMapElement(ele, bd); }
public Map<Object, Object> parseMapElement(Element mapEle, @Nullable BeanDefinition bd) { // 獲取key-type屬性值 String defaultKeyType = mapEle.getAttribute(KEY_TYPE_ATTRIBUTE); // 獲取value-type屬性值 String defaultValueType = mapEle.getAttribute(VALUE_TYPE_ATTRIBUTE); // 獲取entry節點的子節點 List<Element> entryEles = DomUtils.getChildElementsByTagName(mapEle, ENTRY_ELEMENT); ManagedMap<Object, Object> map = new ManagedMap<>(entryEles.size()); map.setSource(extractSource(mapEle)); map.setKeyTypeName(defaultKeyType); map.setValueTypeName(defaultValueType); map.setMergeEnabled(parseMergeAttribute(mapEle)); for (Element entryEle : entryEles) { // Should only have one value child element: ref, value, list, etc. // Optionally, there might be a key child element. NodeList entrySubNodes = entryEle.getChildNodes(); Element keyEle = null; Element valueEle = null; for (int j = 0; j < entrySubNodes.getLength(); j++) { Node node = entrySubNodes.item(j); if (node instanceof Element) { Element candidateEle = (Element) node; // 若是是key節點 if (nodeNameEquals(candidateEle, KEY_ELEMENT)) { if (keyEle != null) { error("<entry> element is only allowed to contain one <key> sub-element", entryEle); } else { keyEle = candidateEle; } } else { // Child element is what we're looking for.若是是description節點 if (nodeNameEquals(candidateEle, DESCRIPTION_ELEMENT)) { // the element is a <description> -> ignore it } else if (valueEle != null) { error("<entry> element must not contain more than one value sub-element", entryEle); } else { valueEle = candidateEle; } } } } // Extract key from attribute or sub-element. Object key = null; // 是否有key屬性 boolean hasKeyAttribute = entryEle.hasAttribute(KEY_ATTRIBUTE); // 是否有key-ref屬性 boolean hasKeyRefAttribute = entryEle.hasAttribute(KEY_REF_ATTRIBUTE); if ((hasKeyAttribute && hasKeyRefAttribute) || (hasKeyAttribute || hasKeyRefAttribute) && keyEle != null) { error("<entry> element is only allowed to contain either " + "a 'key' attribute OR a 'key-ref' attribute OR a <key> sub-element", entryEle); } if (hasKeyAttribute) { key = buildTypedStringValueForMap(entryEle.getAttribute(KEY_ATTRIBUTE), defaultKeyType, entryEle); } else if (hasKeyRefAttribute) { String refName = entryEle.getAttribute(KEY_REF_ATTRIBUTE); if (!StringUtils.hasText(refName)) { error("<entry> element contains empty 'key-ref' attribute", entryEle); } RuntimeBeanReference ref = new RuntimeBeanReference(refName); ref.setSource(extractSource(entryEle)); key = ref; } else if (keyEle != null) { key = parseKeyElement(keyEle, bd, defaultKeyType); } else { error("<entry> element must specify a key", entryEle); } // Extract value from attribute or sub-element. Object value = null; // 是否有value屬性 boolean hasValueAttribute = entryEle.hasAttribute(VALUE_ATTRIBUTE); // 是否有value-ref屬性 boolean hasValueRefAttribute = entryEle.hasAttribute(VALUE_REF_ATTRIBUTE); // 是否有value-type屬性 boolean hasValueTypeAttribute = entryEle.hasAttribute(VALUE_TYPE_ATTRIBUTE); if ((hasValueAttribute && hasValueRefAttribute) || (hasValueAttribute || hasValueRefAttribute) && valueEle != null) { error("<entry> element is only allowed to contain either " + "'value' attribute OR 'value-ref' attribute OR <value> sub-element", entryEle); } if ((hasValueTypeAttribute && hasValueRefAttribute) || (hasValueTypeAttribute && !hasValueAttribute) || (hasValueTypeAttribute && valueEle != null)) { error("<entry> element is only allowed to contain a 'value-type' " + "attribute when it has a 'value' attribute", entryEle); } if (hasValueAttribute) { String valueType = entryEle.getAttribute(VALUE_TYPE_ATTRIBUTE); if (!StringUtils.hasText(valueType)) { valueType = defaultValueType; } value = buildTypedStringValueForMap(entryEle.getAttribute(VALUE_ATTRIBUTE), valueType, entryEle); } else if (hasValueRefAttribute) { String refName = entryEle.getAttribute(VALUE_REF_ATTRIBUTE); if (!StringUtils.hasText(refName)) { error("<entry> element contains empty 'value-ref' attribute", entryEle); } RuntimeBeanReference ref = new RuntimeBeanReference(refName); ref.setSource(extractSource(entryEle)); value = ref; } else if (valueEle != null) { // 遞歸調用 value = parsePropertySubElement(valueEle, bd, defaultValueType); } else { error("<entry> element must specify a value", entryEle); } // Add final key and value to the Map. map.put(key, value); } return map; }
找到這行代碼
// 若是是props節點 else if (nodeNameEquals(ele, PROPS_ELEMENT)) { return parsePropsElement(ele); }
public Properties parsePropsElement(Element propsEle) { ManagedProperties props = new ManagedProperties(); props.setSource(extractSource(propsEle)); props.setMergeEnabled(parseMergeAttribute(propsEle)); // 獲取prop的子節點 List<Element> propEles = DomUtils.getChildElementsByTagName(propsEle, PROP_ELEMENT); for (Element propEle : propEles) { // 獲取key屬性值 String key = propEle.getAttribute(KEY_ATTRIBUTE); // Trim the text value to avoid unwanted whitespace // caused by typical XML formatting. String value = DomUtils.getTextValue(propEle).trim(); TypedStringValue keyHolder = new TypedStringValue(key); keyHolder.setSource(extractSource(propEle)); TypedStringValue valueHolder = new TypedStringValue(value); valueHolder.setSource(extractSource(propEle)); props.put(keyHolder, valueHolder); } return props; }
返回到這個方法
org.springframework.beans.factory.xml.BeanDefinitionParserDelegate#parseCustomElement(org.w3c.dom.Element, org.springframework.beans.factory.config.BeanDefinition)
@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)); }
以上是util的namespace的源碼解析。
總結一下
util注入有幾種類型
一、list
二、set
三、map
四、props
五、array
最後
本次介紹到這裏,以上內容僅供參考。