@Overridepublic 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());}
@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定义 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 element", ele); return null; } } if (!StringUtils.hasText(refName)) { error(" 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); }
@Nullablepublic 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 element", ele); return null; } if (!StringUtils.hasText(refName)) { error(" element contains empty target attribute", ele); return null; } RuntimeBeanNameReference ref = new RuntimeBeanNameReference(refName); ref.setSource(extractSource(ele)); return ref;}
public Map 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 entryEles = DomUtils.getChildElementsByTagName(mapEle, ENTRY_ELEMENT); ManagedMap 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(" element is only allowed to contain one 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 -> ignore it } else if (valueEle != null) { error(" 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(" element is only allowed to contain either " + "a 'key' attribute OR a 'key-ref' attribute OR a 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(" 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(" 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(" element is only allowed to contain either " + "'value' attribute OR 'value-ref' attribute OR sub-element", entryEle); } if ((hasValueTypeAttribute && hasValueRefAttribute) || (hasValueTypeAttribute && !hasValueAttribute) || (hasValueTypeAttribute && valueEle != null)) { error(" 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(" 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(" 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 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; }