Spring源码解析(2)之默认标签的解析(二)

首先感谢 《Spring源码深度解析》郝佳,让我对spring源码有了更深的理解,本篇文章主要是对《Spring源码深度解析》解读的笔记以及自己对书本解读后的理解,本篇文章是对上面一篇Spring源码解析(2)之默认标签的解析(一)的衔接。

⑥:解析子元素constructor-arg

      constructor-arg的使用:
<bean id="car" class="zhuojing.spring.beans.Car">
          <constructor-arg value="Audi" index="0"></constructor-arg>
            <constructor-arg value="Shanghai" index="1"></constructor-arg>
            <constructor-arg value="300000" type="java.lang.Double"></constructor-arg>
       </bean>
       对于constructor-arg 标签的解析spring是通过parseConstructorArgElements函数来实现的。源码如下

     

public void parseConstructorArgElements(Element beanEle, BeanDefinition bd) {
		NodeList nl = beanEle.getChildNodes();
		for (int i = 0; i < nl.getLength(); i++) {
			Node node = nl.item(i);
			if (isCandidateElement(node) && nodeNameEquals(node, CONSTRUCTOR_ARG_ELEMENT)) {
				parseConstructorArgElement((Element) node, bd);
			}
		}
	}

	public void parseConstructorArgElement(Element ele, BeanDefinition bd) {
		//提取index属性
		String indexAttr = ele.getAttribute(INDEX_ATTRIBUTE);
		//提取 type 属性
		String typeAttr = ele.getAttribute(TYPE_ATTRIBUTE);
		//提取 name属性
		String nameAttr = ele.getAttribute(NAME_ATTRIBUTE);
		//存在index属性
		if (StringUtils.hasLength(indexAttr)) {
			try {
				int index = Integer.parseInt(indexAttr);
				if (index < 0) {
					error("'index' cannot be lower than 0", ele);
				}
				else {
					try {
						this.parseState.push(new ConstructorArgumentEntry(index));
						//解析ele对应的属性元素
						Object value = parsePropertyValue(ele, bd, null);
						ConstructorArgumentValues.ValueHolder valueHolder = new ConstructorArgumentValues.ValueHolder(value);
						if (StringUtils.hasLength(typeAttr)) {
							valueHolder.setType(typeAttr);
						}
						if (StringUtils.hasLength(nameAttr)) {
							valueHolder.setName(nameAttr);
						}
						valueHolder.setSource(extractSource(ele));
						//不允许重复指定相同参数
						if (bd.getConstructorArgumentValues().hasIndexedArgumentValue(index)) {
							error("Ambiguous constructor-arg entries for index " + index, ele);
						}
						else {
							bd.getConstructorArgumentValues().addIndexedArgumentValue(index, valueHolder);
						}
					}
					finally {
						this.parseState.pop();
					}
				}
			}
			catch (NumberFormatException ex) {
				error("Attribute 'index' of tag 'constructor-arg' must be an integer", ele);
			}
		}
		else {
			//没有index 属性则忽略去属性,自动寻找
			try {
				this.parseState.push(new ConstructorArgumentEntry());
				Object value = parsePropertyValue(ele, bd, null);
				ConstructorArgumentValues.ValueHolder valueHolder = new ConstructorArgumentValues.ValueHolder(value);
				if (StringUtils.hasLength(typeAttr)) {
					valueHolder.setType(typeAttr);
				}
				if (StringUtils.hasLength(nameAttr)) {
					valueHolder.setName(nameAttr);
				}
				valueHolder.setSource(extractSource(ele));
				bd.getConstructorArgumentValues().addGenericArgumentValue(valueHolder);
			}
			finally {
				this.parseState.pop();
			}
		}
	}parseConstructorArgElements(Element beanEle, BeanDefinition bd) {
		NodeList nl = beanEle.getChildNodes();
		for (int i = 0; i < nl.getLength(); i++) {
			Node node = nl.item(i);
			if (isCandidateElement(node) && nodeNameEquals(node, CONSTRUCTOR_ARG_ELEMENT)) {
				parseConstructorArgElement((Element) node, bd);
			}
		}
	}

	public void parseConstructorArgElement(Element ele, BeanDefinition bd) {
		//提取index属性
		String indexAttr = ele.getAttribute(INDEX_ATTRIBUTE);
		//提取 type 属性
		String typeAttr = ele.getAttribute(TYPE_ATTRIBUTE);
		//提取 name属性
		String nameAttr = ele.getAttribute(NAME_ATTRIBUTE);
		//存在index属性
		if (StringUtils.hasLength(indexAttr)) {
			try {
				int index = Integer.parseInt(indexAttr);
				if (index < 0) {
					error("'index' cannot be lower than 0", ele);
				}
				else {
					try {
						this.parseState.push(new ConstructorArgumentEntry(index));
						//解析ele对应的属性元素
						Object value = parsePropertyValue(ele, bd, null);
						ConstructorArgumentValues.ValueHolder valueHolder = new ConstructorArgumentValues.ValueHolder(value);
						if (StringUtils.hasLength(typeAttr)) {
							valueHolder.setType(typeAttr);
						}
						if (StringUtils.hasLength(nameAttr)) {
							valueHolder.setName(nameAttr);
						}
						valueHolder.setSource(extractSource(ele));
						//不允许重复指定相同参数
						if (bd.getConstructorArgumentValues().hasIndexedArgumentValue(index)) {
							error("Ambiguous constructor-arg entries for index " + index, ele);
						}
						else {
							bd.getConstructorArgumentValues().addIndexedArgumentValue(index, valueHolder);
						}
					}
					finally {
						this.parseState.pop();
					}
				}
			}
			catch (NumberFormatException ex) {
				error("Attribute 'index' of tag 'constructor-arg' must be an integer", ele);
			}
		}
		else {
			//没有index 属性则忽略去属性,自动寻找
			try {
				this.parseState.push(new ConstructorArgumentEntry());
				Object value = parsePropertyValue(ele, bd, null);
				ConstructorArgumentValues.ValueHolder valueHolder = new ConstructorArgumentValues.ValueHolder(value);
				if (StringUtils.hasLength(typeAttr)) {
					valueHolder.setType(typeAttr);
				}
				if (StringUtils.hasLength(nameAttr)) {
					valueHolder.setName(nameAttr);
				}
				valueHolder.setSource(extractSource(ele));
				bd.getConstructorArgumentValues().addGenericArgumentValue(valueHolder);
			}
			finally {
				this.parseState.pop();
			}
		}
	}

 

        以上parseConstructorArgElement 方法的流程步骤为:
如果存在index属性
  ①:解析constructor-arg 的子元素
②:使用ConstructorArgumentValueHolder 类型来封装解析出来的元素
③:将type、name和index属性一并封装在ConstructorArgumentValues.ValueHolder类型中并添加至当前BeanDefinition的constructorArgumentValues的indexedArgumentValuess属性中
如果存在index属性
如果存在index属性
  ①:解析constructor-arg 的子元素
②:使用ConstructorArgumentValueHolder 类型来封装解析出来的元素
③:将type、name和index属性一并封装在ConstructorArgumentValues.ValueHolder类型中并添加至当前BeanDefinition的constructorArgumentValues的genericArgumentValues属性中

 

 

        接着进一步了解构造函数配置中的子元素的过程

  

public Object parsePropertyValue(Element ele, BeanDefinition bd, String propertyName) {
		String elementName = (propertyName != null) ?
						"<property> element for property '" + propertyName + "'" :
						"<constructor-arg> element";

		// 一个属性只能对应一种类型: ref, value, list, etc.
		NodeList nl = ele.getChildNodes();
		Element subElement = null;
		for (int i = 0; i < nl.getLength(); i++) {
			Node node = nl.item(i);
			//对应description 或 meta 不处理
			if (node instanceof Element && !nodeNameEquals(node, DESCRIPTION_ELEMENT) &&
					!nodeNameEquals(node, META_ELEMENT)) {
				// Child element is what we're looking for.
				if (subElement != null) {
					error(elementName + " must not contain more than one sub-element", ele);
				}
				else {
					subElement = (Element) node;
				}
			}
		}
		//解析constructor-arg上的ref属性	
		boolean hasRefAttribute = ele.hasAttribute(REF_ATTRIBUTE);
		//解析constructor-arg 上的value属性
		boolean hasValueAttribute = ele.hasAttribute(VALUE_ATTRIBUTE);
		if ((hasRefAttribute && hasValueAttribute) ||
				((hasRefAttribute || hasValueAttribute) && subElement != null)) {
			/**
			 *在constructor-arg 上不会存在这两种情况
			 *   1、同时既有ref属性又有value属性
                         *   2、存在ref属性或者value属性且又有子元素
                         */	
			error(elementName +
					" is only allowed to contain either 'ref' attribute OR 'value' attribute OR sub-element", ele);
		}
		//ref属性的处理,使用RuntimeBeanReference 封装对应的ref 名称
		if (hasRefAttribute) {
			String refName = ele.getAttribute(REF_ATTRIBUTE);
			if (!StringUtils.hasText(refName)) {
				error(elementName + " contains empty 'ref' attribute", ele);
			}
			RuntimeBeanReference ref = new RuntimeBeanReference(refName);
			ref.setSource(extractSource(ele));
			return ref;
		}
		//value 属性的处理,使用TypedStringvalue封装
		else if (hasValueAttribute) {
			TypedStringValue valueHolder = new TypedStringValue(ele.getAttribute(VALUE_ATTRIBUTE));
			valueHolder.setSource(extractSource(ele));
			return valueHolder;
		}
		else if (subElement != null) {
			//解析子元素
			return parsePropertySubElement(subElement, bd);
		}
		else {
			// 既没有ref属性也没有value属性,也没有子元素
			error(elementName + " must specify a ref or value", ele);
			return null;
		}
	}parsePropertyValue(Element ele, BeanDefinition bd, String propertyName) {
		String elementName = (propertyName != null) ?
						"<property> element for property '" + propertyName + "'" :
						"<constructor-arg> element";

		// 一个属性只能对应一种类型: ref, value, list, etc.
		NodeList nl = ele.getChildNodes();
		Element subElement = null;
		for (int i = 0; i < nl.getLength(); i++) {
			Node node = nl.item(i);
			//对应description 或 meta 不处理
			if (node instanceof Element && !nodeNameEquals(node, DESCRIPTION_ELEMENT) &&
					!nodeNameEquals(node, META_ELEMENT)) {
				// Child element is what we're looking for.
				if (subElement != null) {
					error(elementName + " must not contain more than one sub-element", ele);
				}
				else {
					subElement = (Element) node;
				}
			}
		}
		//解析constructor-arg上的ref属性	
		boolean hasRefAttribute = ele.hasAttribute(REF_ATTRIBUTE);
		//解析constructor-arg 上的value属性
		boolean hasValueAttribute = ele.hasAttribute(VALUE_ATTRIBUTE);
		if ((hasRefAttribute && hasValueAttribute) ||
				((hasRefAttribute || hasValueAttribute) && subElement != null)) {
			/**
			 *在constructor-arg 上不会存在这两种情况
			 *   1、同时既有ref属性又有value属性
                         *   2、存在ref属性或者value属性且又有子元素
                         */	
			error(elementName +
					" is only allowed to contain either 'ref' attribute OR 'value' attribute OR sub-element", ele);
		}
		//ref属性的处理,使用RuntimeBeanReference 封装对应的ref 名称
		if (hasRefAttribute) {
			String refName = ele.getAttribute(REF_ATTRIBUTE);
			if (!StringUtils.hasText(refName)) {
				error(elementName + " contains empty 'ref' attribute", ele);
			}
			RuntimeBeanReference ref = new RuntimeBeanReference(refName);
			ref.setSource(extractSource(ele));
			return ref;
		}
		//value 属性的处理,使用TypedStringvalue封装
		else if (hasValueAttribute) {
			TypedStringValue valueHolder = new TypedStringValue(ele.getAttribute(VALUE_ATTRIBUTE));
			valueHolder.setSource(extractSource(ele));
			return valueHolder;
		}
		else if (subElement != null) {
			//解析子元素
			return parsePropertySubElement(subElement, bd);
		}
		else {
			// 既没有ref属性也没有value属性,也没有子元素
			error(elementName + " must specify a ref or value", ele);
			return null;
		}
	}

        解构造函数配置中的子元素的步骤流程
        ①:略过description 或者meta
②:提取constructor-arg 上的ref和value属性,以便于根据规则验证正确性,其规则在constructor-arg上不存在一下情况
  同时既有ref属性又有value属性
          存在ref属性或者value属性且又有子元素
        
        解析 constructor-arg下的子元素(map、list等)

 

       

public Object parsePropertySubElement(Element ele, BeanDefinition bd) {
		return parsePropertySubElement(ele, bd, null);
	}
	public Object parsePropertySubElement(Element ele, BeanDefinition bd, String defaultValueType) {
		if (!isDefaultNamespace(ele)) {
			return parseNestedCustomElement(ele, bd);
		}
		else if (nodeNameEquals(ele, BEAN_ELEMENT)) {
			BeanDefinitionHolder nestedBd = parseBeanDefinitionElement(ele, bd);
			if (nestedBd != null) {
				nestedBd = decorateBeanDefinitionIfRequired(ele, nestedBd, bd);
			}
			return nestedBd;
		}
		else if (nodeNameEquals(ele, REF_ELEMENT)) {
			// A generic reference to any name of any bean.
			String refName = ele.getAttribute(BEAN_REF_ATTRIBUTE);
			boolean toParent = false;
			if (!StringUtils.hasLength(refName)) {
				// 解析local
				refName = ele.getAttribute(LOCAL_REF_ATTRIBUTE);
				if (!StringUtils.hasLength(refName)) {
					//解析parent 
					refName = ele.getAttribute(PARENT_REF_ATTRIBUTE);
					toParent = true;
					if (!StringUtils.hasLength(refName)) {
						error("'bean', 'local' 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 元素
		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)) {
			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;
		}
	} (Element ele, BeanDefinition bd) {
		return parsePropertySubElement(ele, bd, null);
	}
	public Object parsePropertySubElement(Element ele, BeanDefinition bd, String defaultValueType) {
		if (!isDefaultNamespace(ele)) {
			return parseNestedCustomElement(ele, bd);
		}
		else if (nodeNameEquals(ele, BEAN_ELEMENT)) {
			BeanDefinitionHolder nestedBd = parseBeanDefinitionElement(ele, bd);
			if (nestedBd != null) {
				nestedBd = decorateBeanDefinitionIfRequired(ele, nestedBd, bd);
			}
			return nestedBd;
		}
		else if (nodeNameEquals(ele, REF_ELEMENT)) {
			// A generic reference to any name of any bean.
			String refName = ele.getAttribute(BEAN_REF_ATTRIBUTE);
			boolean toParent = false;
			if (!StringUtils.hasLength(refName)) {
				// 解析local
				refName = ele.getAttribute(LOCAL_REF_ATTRIBUTE);
				if (!StringUtils.hasLength(refName)) {
					//解析parent 
					refName = ele.getAttribute(PARENT_REF_ATTRIBUTE);
					toParent = true;
					if (!StringUtils.hasLength(refName)) {
						error("'bean', 'local' 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 元素
		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)) {
			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;
		}
	} 

解析array 子元素源码(其他解析list、set等子元素跟解析array大同小异,这边只举例array,都是用ManagedArray 类封装下子元素,然后进行解析,最后将ManagedArray 返回):

 

  

public Object parseArrayElement(Element arrayEle, BeanDefinition bd) {
		//获取子元素类型
		String elementType = arrayEle.getAttribute(VALUE_TYPE_ATTRIBUTE);
		//获取子元素的孩子列表
		NodeList nl = arrayEle.getChildNodes();
		//根据子元素的类型声明ManagedArray 
		ManagedArray target = new ManagedArray(elementType, nl.getLength());
		//将子元素转换成Object,存放在ManagedArray,
		target.setSource(extractSource(arrayEle));
		//保存子元素的类型
		target.setElementTypeName(elementType);
		//子元素是否存在merge属性
		target.setMergeEnabled(parseMergeAttribute(arrayEle));
		//解析子元素中的孩子节点(孩子节点为Collection类型)
		parseCollectionElements(nl, target, bd, elementType);
		return target;
	}parseArrayElement(Element arrayEle, BeanDefinition bd) {
		//获取子元素类型
		String elementType = arrayEle.getAttribute(VALUE_TYPE_ATTRIBUTE);
		//获取子元素的孩子列表
		NodeList nl = arrayEle.getChildNodes();
		//根据子元素的类型声明ManagedArray 
		ManagedArray target = new ManagedArray(elementType, nl.getLength());
		//将子元素转换成Object,存放在ManagedArray,
		target.setSource(extractSource(arrayEle));
		//保存子元素的类型
		target.setElementTypeName(elementType);
		//子元素是否存在merge属性
		target.setMergeEnabled(parseMergeAttribute(arrayEle));
		//解析子元素中的孩子节点(孩子节点为Collection类型)
		parseCollectionElements(nl, target, bd, elementType);
		return target;
	}
protected void parseCollectionElements(
			NodeList elementNodes, Collection<Object> target, BeanDefinition bd, String defaultElementType) {
		//遍历子元素的孩子节点
		for (int i = 0; i < elementNodes.getLength(); i++) {
			Node node = elementNodes.item(i);
			if (node instanceof Element && !nodeNameEquals(node, DESCRIPTION_ELEMENT)) {
				//很具子元素的类型,解析孩子节点,并存放在ManagedArray中
				target.add(parsePropertySubElement((Element) node, bd, defaultElementType));
			}
		}
       }parseCollectionElements(
			NodeList elementNodes, Collection<Object> target, BeanDefinition bd, String defaultElementType) {
		//遍历子元素的孩子节点
		for (int i = 0; i < elementNodes.getLength(); i++) {
			Node node = elementNodes.item(i);
			if (node instanceof Element && !nodeNameEquals(node, DESCRIPTION_ELEMENT)) {
				//很具子元素的类型,解析孩子节点,并存放在ManagedArray中
				target.add(parsePropertySubElement((Element) node, bd, defaultElementType));
			}
		}
       }

      ⑦:解析子元素property
             解析property在parsePropertyElements 方法中

 public void parsePropertyElements(Element beanEle, BeanDefinition bd) {
		NodeList nl = beanEle.getChildNodes();
		for (int i = 0; i < nl.getLength(); i++) {
			Node node = nl.item(i);
			if (isCandidateElement(node) && nodeNameEquals(node, PROPERTY_ELEMENT)) {
				parsePropertyElement((Element) node, bd);
			}
		}
	}parsePropertyElements(Element beanEle, BeanDefinition bd) {
		NodeList nl = beanEle.getChildNodes();
		for (int i = 0; i < nl.getLength(); i++) {
			Node node = nl.item(i);
			if (isCandidateElement(node) && nodeNameEquals(node, PROPERTY_ELEMENT)) {
				parsePropertyElement((Element) node, bd);
			}
		}
	}
public void parsePropertyElement(Element ele, BeanDefinition bd) {
		//获取name属性值
		String propertyName = ele.getAttribute(NAME_ATTRIBUTE);
		if (!StringUtils.hasLength(propertyName)) {
			error("Tag 'property' must have a 'name' attribute", ele);
			return;
		}
		this.parseState.push(new PropertyEntry(propertyName));
		try {
			//不允许对此对同一个属性配置
			if (bd.getPropertyValues().contains(propertyName)) {
				error("Multiple 'property' definitions for property '" + propertyName + "'", ele);
				return;
			}
			//解析子元素(根据constructor-arg解析子元素方法一样)
			Object val = parsePropertyValue(ele, bd, propertyName);
			PropertyValue pv = new PropertyValue(propertyName, val);
			parseMetaElements(ele, pv);
			pv.setSource(extractSource(ele));
			bd.getPropertyValues().addPropertyValue(pv);
		}
		finally {
			this.parseState.pop();
		}
	}parsePropertyElement(Element ele, BeanDefinition bd) {
		//获取name属性值
		String propertyName = ele.getAttribute(NAME_ATTRIBUTE);
		if (!StringUtils.hasLength(propertyName)) {
			error("Tag 'property' must have a 'name' attribute", ele);
			return;
		}
		this.parseState.push(new PropertyEntry(propertyName));
		try {
			//不允许对此对同一个属性配置
			if (bd.getPropertyValues().contains(propertyName)) {
				error("Multiple 'property' definitions for property '" + propertyName + "'", ele);
				return;
			}
			//解析子元素(根据constructor-arg解析子元素方法一样)
			Object val = parsePropertyValue(ele, bd, propertyName);
			PropertyValue pv = new PropertyValue(propertyName, val);
			parseMetaElements(ele, pv);
			pv.setSource(extractSource(ele));
			bd.getPropertyValues().addPropertyValue(pv);
		}
		finally {
			this.parseState.pop();
		}
	}

         解析Property 子元素的方法中将property子元素的数据封装到PropertyValue进行封装,并记录在BeanDefinition中的propertyValue属性中

⑧:解析子元素qualifier
     对于qualifier 元素的获取,我们更多的是注解的形式,在Spring框架中进行自动注入。当找不到匹配的Bean时,Spring 容器将抛出BeanCreateException异常,
    并指出必须至少拥有一个匹配的Bean
    Spring允许我们通过Qualifier 指定注入Bean的名称,这样歧义就消除了

 

 

2、AbstractBeanDefinition 属性

      以上完成了对XML文档到GenericBeanDefinition 的转换,也就是XML的所有属性都是存放在GenericBeanDefinition 的实例中
GenericBeanDefinition 只是一个子类实现,二大部分属性都是保存在AbstractBeanDefinition 

     AbstractBeanDefinition 类源码

 

@SuppressWarnings("serial")
	public abstract class AbstractBeanDefinition extends BeanMetadataAttributeAccessor
		implements BeanDefinition, Cloneable {
		//略过常量
		//bean的作用范围,对应bean 属性scope
		private String scope = SCOPE_DEFAULT;
		//是否是抽象
		private boolean abstractFlag = false;
		//是否懒加载
		private boolean lazyInit = false;
		//自动注入
		private int autowireMode = AUTOWIRE_NO;
		//依赖检查,Spring3.0后启用这个属性
		private int dependencyCheck = DEPENDENCY_CHECK_NONE;
		//用来表示一个bean 的实例化依靠另一个bean先实例化,对应属性depend-on
		private String[] dependsOn;
		//对用bean属性的autowire-candidate
		private boolean autowireCandidate = true;
		//自动装配是当出现多个bean候选者是,将作为首选者,对用bean属性primary
		private boolean primary = false;
		//用于记录Qualifier,对应子元素qualifier
		private final Map<String, AutowireCandidateQualifier> qualifiers =
			new LinkedHashMap<String, AutowireCandidateQualifier>(0);
		//运行访问非公开的构造器和方法,程序设置
		private boolean nonPublicAccessAllowed = true;
		//异常抛出,因为Spring 无法确定定位哪个构造函数
		private boolean lenientConstructorResolution = true;
		//记录构造函数注入属性,对用bean属性constructor-arg
		private ConstructorArgumentValues constructorArgumentValues;
		//普通属性集合
		private MutablePropertyValues propertyValues;
		//方法重新的持有者,记录lookup-method、relaced-method元素
		private MethodOverrides methodOverrides = new MethodOverrides();
		//对应bean属性 factory-bean
		private String factoryBeanName;
		//对应bean属性 factory-method
		private String factoryMethodName;
		//初始化方法 对应bean属性的init-method
		private String initMethodName;
		//销毁方法 对应bean属性destory-method
		private String destroyMethodName;
		//是否执行destory-method方法
		private boolean enforceInitMethod = true;
		//是否执行init-method方法
		private boolean enforceDestroyMethod = true;
		//是否是用户定义的而不是应用程序本身定义的,创建AOP时候为true
		private boolean synthetic = false;
		//
		private int role = BeanDefinition.ROLE_APPLICATION;
		//描述信息
		private String description;
		//bean定义的资源
		private Resource resource;
	}AbstractBeanDefinition extends BeanMetadataAttributeAccessor
		implements BeanDefinition, Cloneable {
		//略过常量
		//bean的作用范围,对应bean 属性scope
		private String scope = SCOPE_DEFAULT;
		//是否是抽象
		private boolean abstractFlag = false;
		//是否懒加载
		private boolean lazyInit = false;
		//自动注入
		private int autowireMode = AUTOWIRE_NO;
		//依赖检查,Spring3.0后启用这个属性
		private int dependencyCheck = DEPENDENCY_CHECK_NONE;
		//用来表示一个bean 的实例化依靠另一个bean先实例化,对应属性depend-on
		private String[] dependsOn;
		//对用bean属性的autowire-candidate
		private boolean autowireCandidate = true;
		//自动装配是当出现多个bean候选者是,将作为首选者,对用bean属性primary
		private boolean primary = false;
		//用于记录Qualifier,对应子元素qualifier
		private final Map<String, AutowireCandidateQualifier> qualifiers =
			new LinkedHashMap<String, AutowireCandidateQualifier>(0);
		//运行访问非公开的构造器和方法,程序设置
		private boolean nonPublicAccessAllowed = true;
		//异常抛出,因为Spring 无法确定定位哪个构造函数
		private boolean lenientConstructorResolution = true;
		//记录构造函数注入属性,对用bean属性constructor-arg
		private ConstructorArgumentValues constructorArgumentValues;
		//普通属性集合
		private MutablePropertyValues propertyValues;
		//方法重新的持有者,记录lookup-method、relaced-method元素
		private MethodOverrides methodOverrides = new MethodOverrides();
		//对应bean属性 factory-bean
		private String factoryBeanName;
		//对应bean属性 factory-method
		private String factoryMethodName;
		//初始化方法 对应bean属性的init-method
		private String initMethodName;
		//销毁方法 对应bean属性destory-method
		private String destroyMethodName;
		//是否执行destory-method方法
		private boolean enforceInitMethod = true;
		//是否执行init-method方法
		private boolean enforceDestroyMethod = true;
		//是否是用户定义的而不是应用程序本身定义的,创建AOP时候为true
		private boolean synthetic = false;
		//
		private int role = BeanDefinition.ROLE_APPLICATION;
		//描述信息
		private String description;
		//bean定义的资源
		private Resource resource;
	}


  3、解析默认标签中的自定义标签元素

 

 

 

       再次回顾解析标签函数的开始方法:

 

protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
		//解析bean标签,bdHolder 包含着bean标签的所有属性
		BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
		if (bdHolder != null) {
			//解析自定义标签元素
			bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);
			try {
				// 注册解析
				BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry());
			}
			catch (BeanDefinitionStoreException ex) {
				getReaderContext().error("Failed to register bean definition with name '" +
						bdHolder.getBeanName() + "'", ele, ex);
			}
			// Send registration event.
			getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder));
		}
	}processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
		//解析bean标签,bdHolder 包含着bean标签的所有属性
		BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
		if (bdHolder != null) {
			//解析自定义标签元素
			bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);
			try {
				// 注册解析
				BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry());
			}
			catch (BeanDefinitionStoreException ex) {
				getReaderContext().error("Failed to register bean definition with name '" +
						bdHolder.getBeanName() + "'", ele, ex);
			}
			// Send registration event.
			getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder));
		}
	}

       在上面我们用了很大的篇幅在分析BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);这句话,接下来我们就要解析bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);。

 

       这句代码就是进行自定义标签元素解析的,源码如下

 

 public BeanDefinitionHolder decorateBeanDefinitionIfRequired(Element ele, BeanDefinitionHolder definitionHolder) {
		return decorateBeanDefinitionIfRequired(ele, definitionHolder, null);
       }
       这边decorateBeanDefinitionIfRequired的方法中的第三参数是为了使用父类的scope属性,以备子类若没有设置scope时默认使用父类的属性,这里分析是顶层配置,所有传递null
       public BeanDefinitionHolder decorateBeanDefinitionIfRequired(
			Element ele, BeanDefinitionHolder definitionHolder, BeanDefinition containingBd) {

		BeanDefinitionHolder finalDefinition = definitionHolder;

		// Decorate based on custom attributes first.
		NamedNodeMap attributes = ele.getAttributes();
		//遍历所有的属性,看看是否有使用于修饰的属性
		for (int i = 0; i < attributes.getLength(); i++) {
			Node node = attributes.item(i);
			finalDefinition = decorateIfRequired(node, finalDefinition, containingBd);
		}

		// Decorate based on custom nested elements.
		NodeList children = ele.getChildNodes();
		//遍历所有的子节点,看看是否有适用于修饰的子元素
		for (int i = 0; i < children.getLength(); i++) {
			Node node = children.item(i);
			if (node.getNodeType() == Node.ELEMENT_NODE) {
				finalDefinition = decorateIfRequired(node, finalDefinition, containingBd);
			}
		}
		return finalDefinition;
	}decorateBeanDefinitionIfRequired(Element ele, BeanDefinitionHolder definitionHolder) {
		return decorateBeanDefinitionIfRequired(ele, definitionHolder, null);
       }
       这边decorateBeanDefinitionIfRequired的方法中的第三参数是为了使用父类的scope属性,以备子类若没有设置scope时默认使用父类的属性,这里分析是顶层配置,所有传递null
       public BeanDefinitionHolder decorateBeanDefinitionIfRequired(
			Element ele, BeanDefinitionHolder definitionHolder, BeanDefinition containingBd) {

		BeanDefinitionHolder finalDefinition = definitionHolder;

		// Decorate based on custom attributes first.
		NamedNodeMap attributes = ele.getAttributes();
		//遍历所有的属性,看看是否有使用于修饰的属性
		for (int i = 0; i < attributes.getLength(); i++) {
			Node node = attributes.item(i);
			finalDefinition = decorateIfRequired(node, finalDefinition, containingBd);
		}

		// Decorate based on custom nested elements.
		NodeList children = ele.getChildNodes();
		//遍历所有的子节点,看看是否有适用于修饰的子元素
		for (int i = 0; i < children.getLength(); i++) {
			Node node = children.item(i);
			if (node.getNodeType() == Node.ELEMENT_NODE) {
				finalDefinition = decorateIfRequired(node, finalDefinition, containingBd);
			}
		}
		return finalDefinition;
	}
public BeanDefinitionHolder decorateIfRequired(
			Node node, BeanDefinitionHolder originalDef, BeanDefinition containingBd) {
		//获取自定义标签的命名空间
		String namespaceUri = getNamespaceURI(node);
		//对于非默认标签进行修饰
		if (!isDefaultNamespace(namespaceUri)) {
			NamespaceHandler handler = this.readerContext.getNamespaceHandlerResolver().resolve(namespaceUri);
			//根据命名空间找到对应的处理器
			if (handler != null) {
				//进行修饰
				return handler.decorate(node, originalDef, new ParserContext(this.readerContext, this, containingBd));
			}
			else if (namespaceUri != null && namespaceUri.startsWith("http://www.springframework.org/")) {
				error("Unable to locate Spring NamespaceHandler for XML schema namespace [" + namespaceUri + "]", node);
			}
			else {
				// A custom namespace, not to be handled by Spring - maybe "xml:...".
				if (logger.isDebugEnabled()) {
					logger.debug("No Spring NamespaceHandler found for XML schema namespace [" + namespaceUri + "]");
				}
			}
		}
		return originalDef;
	}decorateIfRequired(
			Node node, BeanDefinitionHolder originalDef, BeanDefinition containingBd) {
		//获取自定义标签的命名空间
		String namespaceUri = getNamespaceURI(node);
		//对于非默认标签进行修饰
		if (!isDefaultNamespace(namespaceUri)) {
			NamespaceHandler handler = this.readerContext.getNamespaceHandlerResolver().resolve(namespaceUri);
			//根据命名空间找到对应的处理器
			if (handler != null) {
				//进行修饰
				return handler.decorate(node, originalDef, new ParserContext(this.readerContext, this, containingBd));
			}
			else if (namespaceUri != null && namespaceUri.startsWith("http://www.springframework.org/")) {
				error("Unable to locate Spring NamespaceHandler for XML schema namespace [" + namespaceUri + "]", node);
			}
			else {
				// A custom namespace, not to be handled by Spring - maybe "xml:...".
				if (logger.isDebugEnabled()) {
					logger.debug("No Spring NamespaceHandler found for XML schema namespace [" + namespaceUri + "]");
				}
			}
		}
		return originalDef;
	}

       以上代码步骤:首先获取属性或者元素的命名空间,以此来判断元素或者属性是否适用于自定义标签的解析条件,找出自定义类型所对应的NamespaceHandler并进行进一步解析

 

 4、注册解析的BeanDefinition

BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry());的解析,源码如下

 

public static void registerBeanDefinition(
			BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry)
			throws BeanDefinitionStoreException {

		// 适用beanName作为唯一标识注册
		String beanName = definitionHolder.getBeanName();
		registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());

		// 注册所有别名
		String[] aliases = definitionHolder.getAliases();
		if (aliases != null) {
			for (String aliase : aliases) {
				registry.registerAlias(beanName, aliase);
			}
		}
	}registerBeanDefinition(
			BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry)
			throws BeanDefinitionStoreException {

		// 适用beanName作为唯一标识注册
		String beanName = definitionHolder.getBeanName();
		registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());

		// 注册所有别名
		String[] aliases = definitionHolder.getAliases();
		if (aliases != null) {
			for (String aliase : aliases) {
				registry.registerAlias(beanName, aliase);
			}
		}
	}

以上代码可以看出,解析的beanDefinition 都会被注册到BeanDefinitionRegistry类型的registry,beanDefinition 注册分为通过beanName注册以及通过别名注册

 

a、通过beanName注册BeanDefinition
    对于beanDefinition 注册,其实就是将beanDefinition 放在map中,使用beam作为key,除此之外Spring还做了其他操作,源码如下(DefaultListableBeanFactory类中)

   

@Override
	public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
			throws BeanDefinitionStoreException {

		Assert.hasText(beanName, "Bean name must not be empty");
		Assert.notNull(beanDefinition, "BeanDefinition must not be null");

		if (beanDefinition instanceof AbstractBeanDefinition) {
			/*
			 *注册前的最后一次,这里的校验不同于之前的XML文件检验
			 *主要是对于AbstractBeanDefinition 属性中的methodOverride是校验
			 *校验methodOverrides是否与工厂方法并存或者methodOverrides对应的方法根本不存在
			 */
			try {
				((AbstractBeanDefinition) beanDefinition).validate();
			}
			catch (BeanDefinitionValidationException ex) {
				throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,
						"Validation of bean definition failed", ex);
			}
		}
		//因为beanDefinitionMap是全局变量,这里定会存在并发的访问的情况
		synchronized (this.beanDefinitionMap) {
			BeanDefinition oldBeanDefinition = this.beanDefinitionMap.get(beanName);
			//处理已经注册的beanName情况
			if (oldBeanDefinition != null) {
				//如果对应的BeanName 已经注册且在配置了bean不允许被覆盖,则抛出异常
				if (!this.allowBeanDefinitionOverriding) {
					throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,
							"Cannot register bean definition [" + beanDefinition + "] for bean '" + beanName +
							"': There is already [" + oldBeanDefinition + "] bound.");
				}
				else if (oldBeanDefinition.getRole() < beanDefinition.getRole()) {
					// e.g. was ROLE_APPLICATION, now overriding with ROLE_SUPPORT or ROLE_INFRASTRUCTURE
					if (this.logger.isWarnEnabled()) {
						this.logger.warn("Overriding user-defined bean definition for bean '" + beanName +
								" with a framework-generated bean definition ': replacing [" +
								oldBeanDefinition + "] with [" + beanDefinition + "]");
					}
				}
				else {
					if (this.logger.isInfoEnabled()) {
						this.logger.info("Overriding bean definition for bean '" + beanName +
								"': replacing [" + oldBeanDefinition + "] with [" + beanDefinition + "]");
					}
				}
			}
			else {
				//记录beanName
				this.beanDefinitionNames.add(beanName);
				this.frozenBeanDefinitionNames = null;
			}
			//将beanDefinition加入到map中
			this.beanDefinitionMap.put(beanName, beanDefinition);
		}
		//重置所有beanName对应的缓存
		resetBeanDefinition(beanName);
	}registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
			throws BeanDefinitionStoreException {

		Assert.hasText(beanName, "Bean name must not be empty");
		Assert.notNull(beanDefinition, "BeanDefinition must not be null");

		if (beanDefinition instanceof AbstractBeanDefinition) {
			/*
			 *注册前的最后一次,这里的校验不同于之前的XML文件检验
			 *主要是对于AbstractBeanDefinition 属性中的methodOverride是校验
			 *校验methodOverrides是否与工厂方法并存或者methodOverrides对应的方法根本不存在
			 */
			try {
				((AbstractBeanDefinition) beanDefinition).validate();
			}
			catch (BeanDefinitionValidationException ex) {
				throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,
						"Validation of bean definition failed", ex);
			}
		}
		//因为beanDefinitionMap是全局变量,这里定会存在并发的访问的情况
		synchronized (this.beanDefinitionMap) {
			BeanDefinition oldBeanDefinition = this.beanDefinitionMap.get(beanName);
			//处理已经注册的beanName情况
			if (oldBeanDefinition != null) {
				//如果对应的BeanName 已经注册且在配置了bean不允许被覆盖,则抛出异常
				if (!this.allowBeanDefinitionOverriding) {
					throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,
							"Cannot register bean definition [" + beanDefinition + "] for bean '" + beanName +
							"': There is already [" + oldBeanDefinition + "] bound.");
				}
				else if (oldBeanDefinition.getRole() < beanDefinition.getRole()) {
					// e.g. was ROLE_APPLICATION, now overriding with ROLE_SUPPORT or ROLE_INFRASTRUCTURE
					if (this.logger.isWarnEnabled()) {
						this.logger.warn("Overriding user-defined bean definition for bean '" + beanName +
								" with a framework-generated bean definition ': replacing [" +
								oldBeanDefinition + "] with [" + beanDefinition + "]");
					}
				}
				else {
					if (this.logger.isInfoEnabled()) {
						this.logger.info("Overriding bean definition for bean '" + beanName +
								"': replacing [" + oldBeanDefinition + "] with [" + beanDefinition + "]");
					}
				}
			}
			else {
				//记录beanName
				this.beanDefinitionNames.add(beanName);
				this.frozenBeanDefinitionNames = null;
			}
			//将beanDefinition加入到map中
			this.beanDefinitionMap.put(beanName, beanDefinition);
		}
		//重置所有beanName对应的缓存
		resetBeanDefinition(beanName);
	}

    以上对于bean的注册处理主要有以下几个步骤
    ①:对AbstractBeanDefinition 的校验,但这边校验跟解析XML文件时候校验不同,解析XML校验是针对XML格式校验,而这边的校验是针对AbstractBeanDefinition的methodOverride是属性的
    ②:对于已经注册的bean,且设置了不允许bean的覆盖,则会抛出异常,否则会直接覆盖
    ③:加入map 缓存

 

          ④:重置beanName对应的缓存

b、通过别名注册BeanDefinition

@Override
	public void registerAlias(String name, String alias) {
		Assert.hasText(name, "'name' must not be empty");
		Assert.hasText(alias, "'alias' must not be empty");
		//如果beanName 与alias 相同的话不记录alias,并删除对应的alias
		if (alias.equals(name)) {
			this.aliasMap.remove(alias);
		}
		else {
			//如果alias 不允许被覆盖则抛出异常
			if (!allowAliasOverriding()) {
				String registeredName = this.aliasMap.get(alias);
				if (registeredName != null && !registeredName.equals(name)) {
					throw new IllegalStateException("Cannot register alias '" + alias + "' for name '" +
							name + "': It is already registered for name '" + registeredName + "'.");
				}
			}
			//当A -> B存在时,若再次出现A -> C -> B
			checkForAliasCircle(name, alias);
			this.aliasMap.put(alias, name);
		}
	}registerAlias(String name, String alias) {
		Assert.hasText(name, "'name' must not be empty");
		Assert.hasText(alias, "'alias' must not be empty");
		//如果beanName 与alias 相同的话不记录alias,并删除对应的alias
		if (alias.equals(name)) {
			this.aliasMap.remove(alias);
		}
		else {
			//如果alias 不允许被覆盖则抛出异常
			if (!allowAliasOverriding()) {
				String registeredName = this.aliasMap.get(alias);
				if (registeredName != null && !registeredName.equals(name)) {
					throw new IllegalStateException("Cannot register alias '" + alias + "' for name '" +
							name + "': It is already registered for name '" + registeredName + "'.");
				}
			}
			//当A -> B存在时,若再次出现A -> C -> B
			checkForAliasCircle(name, alias);
			this.aliasMap.put(alias, name);
		}
	}

    注册别名的代码步骤
   ①:alias与beanName 相同情况处理,若alias与beanName并名称相同则不需要处理并删除掉原有的alias
   ②:alias覆盖处理,若aliasName 已经使用并已经指向了另一beanName则需要用户的设置进行处理
   ③:alias 循环检查。当A -> B存在时,若再次出现A ->C->B时候则会抛出异常
   ④:注册alias

5、通知监听器解析及注册完成
通过getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder));完成通知监听器解析及注册完成

 

6、alias 标签的解析   在对于bean进行定义是,除了使用id属性来指定名称之外,为了提供读个名称,可以使用alias 标签来指定。而所有的这些名称都是

指向同一个bean。在某些情况提供别名非常有用,比如为了让应用的每一个组件能够更容易的对公共组件进行引用
使用方法:

<bean id="testBean" class="com.test"/>
<alias name="testBean" alias="testBean,testBean2" />
alias标签解析的源码如下

 

protected void processAliasRegistration(Element ele) {
		//获取beanName	
		String name = ele.getAttribute(NAME_ATTRIBUTE);
		//获取alias
		String alias = ele.getAttribute(ALIAS_ATTRIBUTE);
		boolean valid = true;
		if (!StringUtils.hasText(name)) {
			getReaderContext().error("Name must not be empty", ele);
			valid = false;
		}
		if (!StringUtils.hasText(alias)) {
			getReaderContext().error("Alias must not be empty", ele);
			valid = false;
		}
		if (valid) {
			try {
				//注册alias
				getReaderContext().getRegistry().registerAlias(name, alias);
			}
			catch (Exception ex) {
				getReaderContext().error("Failed to register alias '" + alias +
						"' for bean with name '" + name + "'", ele, ex);
			}
			//别名注册后通知监听器相应处理
			getReaderContext().fireAliasRegistered(name, alias, extractSource(ele));
		}
	}processAliasRegistration(Element ele) {
		//获取beanName	
		String name = ele.getAttribute(NAME_ATTRIBUTE);
		//获取alias
		String alias = ele.getAttribute(ALIAS_ATTRIBUTE);
		boolean valid = true;
		if (!StringUtils.hasText(name)) {
			getReaderContext().error("Name must not be empty", ele);
			valid = false;
		}
		if (!StringUtils.hasText(alias)) {
			getReaderContext().error("Alias must not be empty", ele);
			valid = false;
		}
		if (valid) {
			try {
				//注册alias
				getReaderContext().getRegistry().registerAlias(name, alias);
			}
			catch (Exception ex) {
				getReaderContext().error("Failed to register alias '" + alias +
						"' for bean with name '" + name + "'", ele, ex);
			}
			//别名注册后通知监听器相应处理
			getReaderContext().fireAliasRegistered(name, alias, extractSource(ele));
		}
	}

从以上代码可以看出alias解析跟之前bean解析大同小异,都是将别名与beanName组成一队注册至registry中
7、Import 标签的解析
Import标签主要是对配置文件进行分模块的作用
使用方法:
<import resource="customerContext.xml"/>
在配置文件中可以使用import的方法导入有模块配置文件,以后若有新模块的加入,那就可以简单修改这个文件了。这样易于管理
源码如下

 

 

 

 

protected void importBeanDefinitionResource(Element ele) {
		//获取resource属性
		String location = ele.getAttribute(RESOURCE_ATTRIBUTE);
		//如果不存在resource 属性则不做任何处理
		if (!StringUtils.hasText(location)) {
			getReaderContext().error("Resource location must not be empty", ele);
			return;
		}

		// 解析系统属性,格式如. "${user.dir}"
		location = environment.resolveRequiredPlaceholders(location);

		Set<Resource> actualResources = new LinkedHashSet<Resource>(4);

		// 判定location 是决定URI还是相对URL
		boolean absoluteLocation = false;
		try {
			absoluteLocation = ResourcePatternUtils.isUrl(location) || ResourceUtils.toURI(location).isAbsolute();
		}
		catch (URISyntaxException ex) {
			// cannot convert to an URI, considering the location relative
			// unless it is the well-known Spring prefix "classpath*:"
		}

		// 如果是绝对URI 则直接根据地质加载对应的配置文件
		if (absoluteLocation) {
			try {
				int importCount = getReaderContext().getReader().loadBeanDefinitions(location, actualResources);
				if (logger.isDebugEnabled()) {
					logger.debug("Imported " + importCount + " bean definitions from URL location [" + location + "]");
				}
			}
			catch (BeanDefinitionStoreException ex) {
				getReaderContext().error(
						"Failed to import bean definitions from URL location [" + location + "]", ele, ex);
			}
		}
		else {
			// 如果是相对地址则根据相对地址计算出绝对地址
			try {
				int importCount;
				//Resource 存在多个子实现类,如VfsResource、FileSystemResource
				Resource relativeResource = getReaderContext().getResource().createRelative(location);
				if (relativeResource.exists()) {
					importCount = getReaderContext().getReader().loadBeanDefinitions(relativeResource);
					actualResources.add(relativeResource);
				}
				else {
					//如果解析不成功,则使用默认的解析器ResourcePatternResolver进行解析
					String baseLocation = getReaderContext().getResource().getURL().toString();
					importCount = getReaderContext().getReader().loadBeanDefinitions(
							StringUtils.applyRelativePath(baseLocation, location), actualResources);
				}
				if (logger.isDebugEnabled()) {
					logger.debug("Imported " + importCount + " bean definitions from relative location [" + location + "]");
				}
			}
			catch (IOException ex) {
				getReaderContext().error("Failed to resolve current resource location", ele, ex);
			}
			catch (BeanDefinitionStoreException ex) {
				getReaderContext().error("Failed to import bean definitions from relative location [" + location + "]",
						ele, ex);
			}
		}
		//解析后进行监听激活处理
		Resource[] actResArray = actualResources.toArray(new Resource[actualResources.size()]);
		getReaderContext().fireImportProcessed(location, actResArray, extractSource(ele));
	}importBeanDefinitionResource(Element ele) {
		//获取resource属性
		String location = ele.getAttribute(RESOURCE_ATTRIBUTE);
		//如果不存在resource 属性则不做任何处理
		if (!StringUtils.hasText(location)) {
			getReaderContext().error("Resource location must not be empty", ele);
			return;
		}

		// 解析系统属性,格式如. "${user.dir}"
		location = environment.resolveRequiredPlaceholders(location);

		Set<Resource> actualResources = new LinkedHashSet<Resource>(4);

		// 判定location 是决定URI还是相对URL
		boolean absoluteLocation = false;
		try {
			absoluteLocation = ResourcePatternUtils.isUrl(location) || ResourceUtils.toURI(location).isAbsolute();
		}
		catch (URISyntaxException ex) {
			// cannot convert to an URI, considering the location relative
			// unless it is the well-known Spring prefix "classpath*:"
		}

		// 如果是绝对URI 则直接根据地质加载对应的配置文件
		if (absoluteLocation) {
			try {
				int importCount = getReaderContext().getReader().loadBeanDefinitions(location, actualResources);
				if (logger.isDebugEnabled()) {
					logger.debug("Imported " + importCount + " bean definitions from URL location [" + location + "]");
				}
			}
			catch (BeanDefinitionStoreException ex) {
				getReaderContext().error(
						"Failed to import bean definitions from URL location [" + location + "]", ele, ex);
			}
		}
		else {
			// 如果是相对地址则根据相对地址计算出绝对地址
			try {
				int importCount;
				//Resource 存在多个子实现类,如VfsResource、FileSystemResource
				Resource relativeResource = getReaderContext().getResource().createRelative(location);
				if (relativeResource.exists()) {
					importCount = getReaderContext().getReader().loadBeanDefinitions(relativeResource);
					actualResources.add(relativeResource);
				}
				else {
					//如果解析不成功,则使用默认的解析器ResourcePatternResolver进行解析
					String baseLocation = getReaderContext().getResource().getURL().toString();
					importCount = getReaderContext().getReader().loadBeanDefinitions(
							StringUtils.applyRelativePath(baseLocation, location), actualResources);
				}
				if (logger.isDebugEnabled()) {
					logger.debug("Imported " + importCount + " bean definitions from relative location [" + location + "]");
				}
			}
			catch (IOException ex) {
				getReaderContext().error("Failed to resolve current resource location", ele, ex);
			}
			catch (BeanDefinitionStoreException ex) {
				getReaderContext().error("Failed to import bean definitions from relative location [" + location + "]",
						ele, ex);
			}
		}
		//解析后进行监听激活处理
		Resource[] actResArray = actualResources.toArray(new Resource[actualResources.size()]);
		getReaderContext().fireImportProcessed(location, actResArray, extractSource(ele));
	}

以上解析Import 标签代码步骤
①:获取resource 属性所表示的路径
②:解析路径中的系统属性,格式如“${user.dir}”
③:判定location 是绝对另还是相对路径
④:如果是绝对路径则递归调用bean的解析过程,进行另一次的解析
⑤:如果是相对路径则计算出绝对路径并进行解析
⑥:通知监听器,解析完成

 

 8、嵌入式beans标签的解析
嵌入式beans标签的解析非常类似于import 标签所提供的功能,这个和单独的配置文件并没有太大的差别,无非是递归调用beans的解析过程,跟以上步骤一样



   9、默认标签解析流程总结(bean标签,其他标签大同小异)
①:BeanDefinitionParserDelegate 类的parseBeanDefinitionElement方法进行元素解析,返回BeanDefinitionHolder 实例,返回的BeanDefinitionHolder 实例中包含bean标签的各中属性
BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
        a:提取元素中的id和name 属性
        b:进一步解析其他所有属性并统一封装到GenericBeanDefinition 类型的实例中
        c:如果检测到bean没有beanName,那么会使用默认的规则生成beanName
        d:将获取到的信息封装到BeanDefinitionHolder
②:解析子节点的自定义属性:bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder)
        a:获取属性或者元素的命名空间,根据属性或者元素的命名空间来判断是否是自定义标签,然后进行解析
③:注册解析的BeanDefinition(map缓存的形式)
        a:通过beanName注册BeanDefinition(不允许bean的覆盖)
        b:通过别名注册BeanDefinitio
④:通知监听器解析及注册完成

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值