spring源码-2.2.默认标签的解析

上一节中,我们详细分析了spring在解析xml,创建beanFactory的前期准备工作,这一节我们将会详细分析一下spring是如何解析系统默认标签的。
首先进入解析默认标签方法的入口,parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate):

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标签的解析
	else if (delegate.nodeNameEquals(ele, BEAN_ELEMENT)) {
		processBeanDefinition(ele, delegate);
	}
	//bean标签的解析
	else if (delegate.nodeNameEquals(ele, NESTED_BEANS_ELEMENT)) {
		doRegisterBeanDefinitions(ele);
	}
}

这边我们就看看bean标签的解析过程,processBeanDefinition(ele, delegate):

protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
    //解析document对象为一个BeanDefinitionHolder对象
	BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
	if (bdHolder != null) {
		bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);
		try {
			//将解析出来的BeanDefinitionHolder对象注册到applicationContext上
			BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry());
		}
		catch (BeanDefinitionStoreException ex) {
			getReaderContext().error("Failed to register bean definition with name '" +
					bdHolder.getBeanName() + "'", ele, ex);
		}
		//发布一个注册成功的event
		getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder));
	}
}

继续进入解析document对象的代码,delegate.parseBeanDefinitionElement(ele):

public BeanDefinitionHolder (Element ele, @Nullable BeanDefinition containingBean) {
    //获取bean标签的id属性和name属性
	String id = ele.getAttribute(ID_ATTRIBUTE);
	String nameAttr = ele.getAttribute(NAME_ATTRIBUTE);
    //获取bean标签的别名属性
	List<String> aliases = new ArrayList<>();
	if (StringUtils.hasLength(nameAttr)) {
		String[] nameArr = StringUtils.tokenizeToStringArray(nameAttr, MULTI_VALUE_ATTRIBUTE_DELIMITERS);
		aliases.addAll(Arrays.asList(nameArr));
	}

    //如果标签没有定义id,并且存在别名,则使用第一个别名作为beanName
	String beanName = id;
	if (!StringUtils.hasText(beanName) && !aliases.isEmpty()) {
		beanName = aliases.remove(0);
		if (logger.isTraceEnabled()) {
			logger.trace("No XML 'id' specified - using '" + beanName +
					"' as bean name and " + aliases + " as aliases");
		}
	}

	if (containingBean == null) {
	    //校验beanName和aliases之前没有使用过,delegate对象中使用两个set去记录
		checkNameUniqueness(beanName, aliases, ele);
	}

    //解析出beanDefinition对象
	AbstractBeanDefinition beanDefinition = parseBeanDefinitionElement(ele, beanName, containingBean);
	if (beanDefinition != null) {
	    //如果没有beanName,则根据beanDefiNition生成一个beanName
		if (!StringUtils.hasText(beanName)) {
			……
		}
		String[] aliasesArray = StringUtils.toStringArray(aliases);
		//封装出BeanDefinitionHolder对象并返回
		return new BeanDefinitionHolder(beanDefinition, beanName, aliasesArray);
	}

	return null;
}

进入解析beanDefinition对象的代码,parseBeanDefinitionElement(ele, beanName, containingBean):

public AbstractBeanDefinition parseBeanDefinitionElement(
			Element ele, String beanName, @Nullable BeanDefinition containingBean) {
    //设置解析状态
	this.parseState.push(new BeanEntry(beanName));
    //获取className和parent
	String className = null;
	if (ele.hasAttribute(CLASS_ATTRIBUTE)) {
		className = ele.getAttribute(CLASS_ATTRIBUTE).trim();
	}
	String parent = null;
	if (ele.hasAttribute(PARENT_ATTRIBUTE)) {
		parent = ele.getAttribute(PARENT_ATTRIBUTE);
	}

	try {
	    //初始化一个GenericBeanDefinition,
	    //如果readerContext对象中有classload,那么加载该类并设置beanClass属性
	    //如果没有classload对象,那么就将className设置为beanClassName属性
		AbstractBeanDefinition bd = createBeanDefinition(className, parent);
        /**
        * 解析bean标签的属性,如果没有配置,则会到default属性中看看有没有
        * 1.设置scope属性
        * 2.设置abstract属性
        * 3.设置lazy-init属性,默认false
        * 4.设置autowireMode属性,分别有0-no,1-byName,2-byType,3-constructor,4-autodetect
        * 5.设置depend-on属性
        * 6.设置autowire-candidate属性
        * 7.设置primary属性
        * 8.设置init-method属性
        * 9.设置destroy-method属性
        * 10.设置factory-method属性
        * 11.设置factory-bean属性
        */
		parseBeanDefinitionAttributes(ele, beanName, containingBean, bd);
		//如果有description子标签,则设置其描述信息
		bd.setDescription(DomUtils.getChildElementValueByTagName(ele, DESCRIPTION_ELEMENT));

        //解析元数据标签 <meta>标签的key,value
		parseMetaElements(ele, bd);
		//解析lookup-method标签,为本类中的某个抽象方法设置返回值
		parseLookupOverrideSubElements(ele, bd.getMethodOverrides());
		//解析replaced-method标签,替换本类中的方法的内容
		parseReplacedMethodSubElements(ele, bd.getMethodOverrides());
        //解析构造函数标签,并将构造函数参数的信息存入constructorArgumentValues
		parseConstructorArgElements(ele, bd);
		//解析property标签,并将值的信息存入到propertyValues
		parsePropertyElements(ele, bd);
		//解析qualifier标签,并将要注入的对象信息存入qualifiers属性中
		parseQualifierElements(ele, bd);
        //设置beanDefinition的Resource和Source
		bd.setResource(this.readerContext.getResource());
		bd.setSource(extractSource(ele));

		return bd;
	}
	catch ……
	finally {
	    //清除状态
		this.parseState.pop();
	}

	return null;
}

到这里,我们就获取到了BeanDefinitionHolder对象,最后我们在看一下注册的逻辑:

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

	String beanName = definitionHolder.getBeanName();
	//注册beanDefinition
	registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());
    //如果有别名,则记录别名和beanName的映射
	String[] aliases = definitionHolder.getAliases();
	if (aliases != null) {
		for (String alias : aliases) {
			registry.registerAlias(beanName, alias);
		}
	}
}

进入注册代码,registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition()):

public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
			throws BeanDefinitionStoreException {
	……校验代码省略
	BeanDefinition existingDefinition = this.beanDefinitionMap.get(beanName);
	if (existingDefinition != null) {
	    //已经注册过
		if (!isAllowBeanDefinitionOverriding()) {
			throw new BeanDefinitionOverrideException(beanName, beanDefinition, existingDefinition);
		}
		……日志打印省略
		//覆盖原来的注册
		this.beanDefinitionMap.put(beanName, beanDefinition);
	}
	else {
	    //如果有bean已经创建了,beanDefinitionNames的就不能modify,所以要重新new一个
		if (hasBeanCreationStarted()) {
			// Cannot modify startup-time collection elements anymore (for stable iteration)
			synchronized (this.beanDefinitionMap) {
				this.beanDefinitionMap.put(beanName, beanDefinition);
				List<String> updatedDefinitions = new ArrayList<>(this.beanDefinitionNames.size() + 1);
				updatedDefinitions.addAll(this.beanDefinitionNames);
				updatedDefinitions.add(beanName);
				this.beanDefinitionNames = updatedDefinitions;
				removeManualSingletonName(beanName);
			}
		}
		else {
			this.beanDefinitionMap.put(beanName, beanDefinition);
			this.beanDefinitionNames.add(beanName);
			//manualSingletonNames中将beanName移除,manualSingletonNames是用来缓存手动注册的单例bean的
			removeManualSingletonName(beanName);
		}
		this.frozenBeanDefinitionNames = null;
	}

	if (existingDefinition != null || containsSingleton(beanName)) {
	    //递归清除这个beanName和它的子类的所有缓存
		resetBeanDefinition(beanName);
	}
}

至此,一个系统标签的解析就已经完成了,下面我们来做一个小结:

  1. 首先会根据标签的类型进行不同的解析,import是import的解析,bean是bean的,这里是拿bean的解析为例
  2. 通过解析element对象,生成一个BeanDefinitionHolder对象
    2.1 解析beanName
    2.2 通过beanName创建一个beanDefinition
    2.3 解析标签属性,并将结果存入beanDefinition
    2.4 解析子标签内容,并将结果存入beanDefinition
    2.5 将beanDefinition包装成BeanDefinitionHolder,并返回
  3. 将这个BeanDefinitionHolder对象注册到applicationContext
发布了81 篇原创文章 · 获赞 16 · 访问量 20万+

猜你喜欢

转载自blog.csdn.net/mazhen1991/article/details/100066944