Spring源码解读2——Bean资源的载入/解析

当Spring的IoC容器将Bean定义的资源文件封装为Spring的Resource之后,接下来要做的就是通过Spring的资源加载器(resourceLoader)读入Bean定义资源文件的过程。对于IoC容器来说,Bean定义的载入过程就是将Bean定义资源文件读入进内存并解析转换成Spring所管理的Bean的数据结构的过程。

Reader的类图:

上一节中实现类加载的入口:

public abstract class AbstractBeanDefinitionReader {

    public int loadBeanDefinitions(String location, Set<Resource> actualResources) {
        // 获取在IoC容器初始化过程中设置的资源加载器(AbstractXmlApplicationContext)
        //即beanDefinitionReader.setResourceLoader(this);
        ResourceLoader resourceLoader = getResourceLoader();
        // 加载单个指定位置的Bean定义资源文件
        Resource resource = resourceLoader.getResource(location);
        // 委派调用其子类XmlBeanDefinitionReader的方法,实现加载功能
        int loadCount = loadBeanDefinitions(resource);
        return loadCount;
    }
}

实现: 

public class XmlBeanDefinitionReader{
        //将读入的XML资源进行特殊编码处理 
        public int loadBeanDefinitions(Resource resource) throws BeanDefinitionStoreException {
		return loadBeanDefinitions(new EncodedResource(resource));
	}

	public int loadBeanDefinitions(EncodedResource encodedResource) throws BeanDefinitionStoreException {
		Assert.notNull(encodedResource, "EncodedResource must not be null");
		if (logger.isInfoEnabled()) {
			logger.info("Loading XML bean definitions from " + encodedResource.getResource());
		}

		Set<EncodedResource> currentResources = this.resourcesCurrentlyBeingLoaded.get();
		if (currentResources == null) {
			currentResources = new HashSet<EncodedResource>(4);
			this.resourcesCurrentlyBeingLoaded.set(currentResources);
		}
		if (!currentResources.add(encodedResource)) {
			throw new BeanDefinitionStoreException(
					"Detected cyclic loading of " + encodedResource + " - check your import definitions!");
		}
		try {
                        //将资源文件转换为IO输入流 
			InputStream inputStream = encodedResource.getResource().getInputStream();
			try {
				InputSource inputSource = new InputSource(inputStream);
				if (encodedResource.getEncoding() != null) {
					inputSource.setEncoding(encodedResource.getEncoding());
				}
                                //具体读取过程的方法
				return doLoadBeanDefinitions(inputSource, encodedResource.getResource());
			}
			finally {
				inputStream.close();
			}
		}
		catch (IOException ex) {
			throw new BeanDefinitionStoreException(
					"IOException parsing XML document from " + encodedResource.getResource(), ex);
		}
		finally {
			currentResources.remove(encodedResource);
			if (currentResources.isEmpty()) {
				this.resourcesCurrentlyBeingLoaded.remove();
			}
		}
	}

        //具体读取过程的方法
        protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource){
		try {
			int validationMode = getValidationModeForResource(resource);
                        //将XML文件转换为DOM对象,解析过程由documentLoader实现 
			Document doc = this.documentLoader.loadDocument(
					inputSource, getEntityResolver(), this.errorHandler, validationMode, isNamespaceAware());

                        //这里是启动对Bean定义解析的详细过程,该解析过程会用到Spring的Bean/配置规则 
			return registerBeanDefinitions(doc, resource);
		}
		catch (BeanDefinitionStoreException ex) {
			throw ex;
		}
	}

        public int registerBeanDefinitions(Document doc, Resource resource){
                //这里得到BeanDefinitionDocumentReader来对XML的BeanDefinition进行解析
		BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader();
		int countBefore = getRegistry().getBeanDefinitionCount();
                //具体的解析过程在这个registerBeanDefinitions中完成
                //BeanDefinitionDocumentReader只是个接口,具体的解析实现过程由实现类                                                                       //DefaultBeanDefinitionDocumentReader完成 
		documentReader.registerBeanDefinitions(doc, createReaderContext(resource));
                //统计解析的Bean数量
		return getRegistry().getBeanDefinitionCount() - countBefore;
	}
        //创建BeanDefinitionDocumentReader对象,解析Document对象(为何要以这种形式创建)
	protected BeanDefinitionDocumentReader createBeanDefinitionDocumentReader() {
                //private Class documentReaderClass = DefaultBeanDefinitionDocumentReader.class;
		return BeanDefinitionDocumentReader.class.cast(BeanUtils.instantiateClass(this.documentReaderClass));
                //反射?
	}
}
public class DefaultBeanDefinitionDocumentReader{

        public void registerBeanDefinitions(Document doc, XmlReaderContext readerContext) {
                //获得XML描述符 
		this.readerContext = readerContext;
	  	logger.debug("Loading bean definitions");
                //获得Document的根元素
		Element root = doc.getDocumentElement();
                //具体的解析过程由BeanDefinitionParserDelegate实现,  
                //BeanDefinitionParserDelegate中定义了Spring Bean定义XML文件的各种元素  
		BeanDefinitionParserDelegate delegate = createHelper(readerContext, root);
                //在解析Bean定义之前,进行自定义的解析,增强解析过程的可扩展性
		preProcessXml(root);
                //从Document的根元素开始进行Bean定义的Document对象  
		parseBeanDefinitions(root, delegate);
                //在解析Bean定义之后,进行自定义的解析,增加解析过程的可扩展性  
		postProcessXml(root);
	}

	protected BeanDefinitionParserDelegate createHelper(XmlReaderContext readerContext, Element root) {
		BeanDefinitionParserDelegate delegate = new BeanDefinitionParserDelegate(readerContext);
                //BeanDefinitionParserDelegate初始化Document根元素  
		delegate.initDefaults(root);
		return delegate;
	}

	protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) {
                //Bean定义的Document对象是否使用了Spring默认的XML命名空间
		if (delegate.isDefaultNamespace(root)) {
                        //获取Bean定义的Document对象根元素的所有子节点 
			NodeList nl = root.getChildNodes();
			for (int i = 0; i < nl.getLength(); i++) {
				Node node = nl.item(i);
                                //获得Document节点是XML元素节点
                                //循环的时候每次只获得一个<Bean>元素
				if (node instanceof Element) {
					Element ele = (Element) node;
                                        //Bean定义的Document的元素节点使用的是Spring默认的XML命名空间  
					if (delegate.isDefaultNamespace(ele)) {
                                                //使用Spring的Bean规则解析元素节点 
						parseDefaultElement(ele, delegate);
					}
					else {
                                                //没有使用Spring默认的XML命名空间,则使用用户自定义的解//析规则解析元素节点  
						delegate.parseCustomElement(ele);
					}
				}
			}
		}
		else {
                        //Document的根节点没有使用Spring默认的命名空间,则使用用户自定义的  
                        //解析规则解析Document根节点 
			delegate.parseCustomElement(root);
		}
	}
以下都是对上述方法for循环中的ele进行解析

=============================================================================================================================

	private void parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate) {
                //如果元素节点是<Import>导入元素,进行导入解析
		if (delegate.nodeNameEquals(ele, IMPORT_ELEMENT)) {
			importBeanDefinitionResource(ele);
		}
                //如果元素节点是<Alias>别名元素,进行别名解析  
		else if (delegate.nodeNameEquals(ele, ALIAS_ELEMENT)) {
			processAliasRegistration(ele);
		}
                //元素节点既不是导入元素,也不是别名元素,即普通的<Bean>元素,  
                //按照Spring的Bean规则解析元素 
		else if (delegate.nodeNameEquals(ele, BEAN_ELEMENT)) {
			processBeanDefinition(ele, delegate);
		}
	}

*********解析的核心

	protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
                //对于既不是<Import>元素,又不是<Alias>元素的元素,即Spring配置文件中普通的<Bean>元素
                //的解析由BeanDefinitionParserDelegate类的parseBeanDefinitionElement方法来实现。

                //一个holder里放一个AbstractBeanDefinition,循环上面的for,把所有的hoder都放入                //BeanDefinitionReaderUtils.registerBeanDefinition(肯定是个单例)
		BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
		if (bdHolder != null) {
			bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);
			try {
				//向Spring IoC容器注册解析得到的Bean定义,这是Bean定义向IoC容器注册的入
				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));
		}
	}
}
public class BeanDefinitionParserDelegate {

        //解析Bean定义资源文件中的<Bean>元素,这个方法中主要处理<Bean>元素的id,name  
        //和别名属性
	public BeanDefinitionHolder parseBeanDefinitionElement(Element ele, BeanDefinition containingBean) {
                //获取<Bean>元素中的id属性值
		String id = ele.getAttribute(ID_ATTRIBUTE);
                //获取<Bean>元素中的name属性值  
		String nameAttr = ele.getAttribute(NAME_ATTRIBUTE);

		List<String> aliases = new ArrayList<String>();
		if (StringUtils.hasLength(nameAttr)) {
			String[] nameArr = StringUtils.tokenizeToStringArray(nameAttr, BEAN_NAME_DELIMITERS);
			aliases.addAll(Arrays.asList(nameArr));
		}

		String beanName = id;
		if (!StringUtils.hasText(beanName) && !aliases.isEmpty()) {
			beanName = aliases.remove(0);
			if (logger.isDebugEnabled()) {
				logger.debug("No XML 'id' specified - using '" + beanName +
						"' as bean name and " + aliases + " as aliases");
			}
		}

		if (containingBean == null) {
			checkNameUniqueness(beanName, aliases, ele);
		}

                //详细对<Bean>元素中配置的Bean定义进行解析的地方  
                //一个holder里放一个AbstractBeanDefinition
		AbstractBeanDefinition beanDefinition = parseBeanDefinitionElement(ele, beanName, containingBean);
                ......
                return new BeanDefinitionHolder(beanDefinition, beanName, aliasesArray); 
        }

        //详细对<Bean>元素中配置的Bean定义其他属性进行解析,由于上面的方法中已经对Bean的id、name和别名等属性进行了处理,
        //该方法中主要处理除这三个以外的其他属性数据 
        public AbstractBeanDefinition parseBeanDefinitionElement(
			Element ele, String beanName, BeanDefinition containingBean) {
                //记录解析的<Bean>
		this.parseState.push(new BeanEntry(beanName));
                //这里只读取<Bean>元素中配置的class名字,然后载入到BeanDefinition中去  
                //只是记录配置的class名字,不做实例化,对象的实例化在依赖注入时完成  
		String className = null;
		if (ele.hasAttribute(CLASS_ATTRIBUTE)) {
			className = ele.getAttribute(CLASS_ATTRIBUTE).trim();
		}

		try {
			String parent = null;
			if (ele.hasAttribute(PARENT_ATTRIBUTE)) {
				parent = ele.getAttribute(PARENT_ATTRIBUTE);
			}
                        //根据<Bean>元素配置的class名称和parent属性值创建BeanDefinition  
                        //为载入Bean定义信息做准备 
			AbstractBeanDefinition bd = createBeanDefinition(className, parent);

			parseBeanDefinitionAttributes(ele, beanName, containingBean, bd);
			bd.setDescription(DomUtils.getChildElementValueByTagName(ele, DESCRIPTION_ELEMENT));

			parseMetaElements(ele, bd);
			parseLookupOverrideSubElements(ele, bd.getMethodOverrides());
			parseReplacedMethodSubElements(ele, bd.getMethodOverrides());

			parseConstructorArgElements(ele, bd);
                        //解析<Bean>元素的<property>设置
			parsePropertyElements(ele, bd);
			parseQualifierElements(ele, bd);

			bd.setResource(this.readerContext.getResource());
			bd.setSource(extractSource(ele));

			return bd;
		}
		return null;
	}
BeanDefinitionParserDelegate在解析<Bean>调用parsePropertyElements方法解析<Bean>元素中的<property>属性子元素,解析源码如下:

	public void parsePropertyElements(Element beanEle, BeanDefinition bd) {
                //获取<Bean>元素中所有的子元素 
		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);
			}
		}
	}
        =============================================================
        //又开始循环上面的for,解析每一个<property>

	public void parsePropertyElement(Element ele, BeanDefinition bd) {
                //获取<property>元素的名字 
		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;
			}
                        //解析获取property的值 
			Object val = parsePropertyValue(ele, bd, propertyName);
                        //根据property的名字和值创建property实例  
                        PropertyValue pv = new PropertyValue(propertyName, val);  
                        //解析<property>元素中的属性  
                        parseMetaElements(ele, pv);  
                        pv.setSource(extractSource(ele));  
                        property以pv的形式放入bd里

                       //
                        bd.getPropertyValues().addPropertyValue(pv); 
        }

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

		//获取<property>的所有子元素,只能是其中一种类型:ref,value,list等  
		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;
				}
			}
		}
                 //判断property的属性值是ref还是value,不允许既是ref又是value  
		boolean hasRefAttribute = ele.hasAttribute(REF_ATTRIBUTE);
		boolean hasValueAttribute = ele.hasAttribute(VALUE_ATTRIBUTE);
                 
		if ((hasRefAttribute && hasValueAttribute) ||
				((hasRefAttribute || hasValueAttribute) && subElement != null)) {
			error(elementName +
					" is only allowed to contain either 'ref' attribute OR 'value' attribute OR sub-element", ele);
		}
                //如果属性是ref,创建一个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的数据对象是被当前的property对象所引用 
			ref.setSource(extractSource(ele));
			return ref;
		}
		else if (hasValueAttribute) {

                        //pv的val是这种类型的
			TypedStringValue valueHolder = new TypedStringValue(ele.getAttribute(VALUE_ATTRIBUTE));
			valueHolder.setSource(extractSource(ele));
			return valueHolder;
		}
                //如果当前<property>元素还有子元素  
		else if (subElement != null) {
                        //解析<property>的子元素 
			return parsePropertySubElement(subElement, bd);
		}
		else {
			// Neither child element nor "ref" or "value" attribute found.
			error(elementName + " must specify a ref or value", ele);
			return null;
		}
	}


	public Object parsePropertySubElement(Element ele, BeanDefinition bd, String defaultValueType) {
                //如果<property>没有使用Spring默认的命名空间,则使用用户自定义的规则解析内嵌元素
		if (!isDefaultNamespace(ele)) {
			return parseNestedCustomElement(ele, bd);
		}
                //如果子元素是bean,则使用解析<Bean>元素的方法解析
		else if (nodeNameEquals(ele, BEAN_ELEMENT)) {
			BeanDefinitionHolder nestedBd = parseBeanDefinitionElement(ele, bd);
			if (nestedBd != null) {
				nestedBd = decorateBeanDefinitionIfRequired(ele, nestedBd, bd);
			}
			return nestedBd;
		}
                //如果子元素是ref,ref中只能有以下3个属性:bean、local、parent 
		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)) {
				// A reference to the id of another bean in the same XML file.
				refName = ele.getAttribute(LOCAL_REF_ATTRIBUTE);
				if (!StringUtils.hasLength(refName)) {
					// A reference to the id of another bean in a parent context.
					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;
		}
		else if (nodeNameEquals(ele, IDREF_ELEMENT)) {
			return parseIdRefElement(ele);
		}
		else if (nodeNameEquals(ele, VALUE_ELEMENT)) {
			return parseValueElement(ele, defaultValueType);
		}
		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;
		}
		else if (nodeNameEquals(ele, ARRAY_ELEMENT)) {
			return parseArrayElement(ele, bd);
		}
                //如果子元素是<list>,使用解析list集合子元素的方法解析 
		else if (nodeNameEquals(ele, LIST_ELEMENT)) {
			return parseListElement(ele, bd);
		}
		else if (nodeNameEquals(ele, SET_ELEMENT)) {
			return parseSetElement(ele, bd);
		}
		else if (nodeNameEquals(ele, MAP_ELEMENT)) {
			return parseMapElement(ele, bd);
		}
		else if (nodeNameEquals(ele, PROPS_ELEMENT)) {
			return parsePropsElement(ele);
		}
		else {
			error("Unknown property sub-element: [" + ele.getNodeName() + "]", ele);
			return null;
		}
	}
}

解析后的bean资源的数据结构:

(Obj)TypedStringValue valueHolder(即val)->PropertyValue(propertyName, val)->AbstractBeanDefinition->
[BeanDefinitionHolder(beanDefinition,beanName)]->(Map)beanDefinitionMap

转载于:https://my.oschina.net/u/2286010/blog/704886

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值