Spring IOC系列学习笔记三:parseDefaultElement详解

本文详细解读Spring IoC中<bean>标签的解析流程,包括元素属性解析、构造参数、属性值处理和BeanDefinition注册,展示了BeanDefinitionHolder的构建与BeanFactory缓存的作用。
摘要由CSDN通过智能技术生成

原文地址程序员囧辉大佬

相关文章

Spring IOC系列学习笔记一:前置刷新
Spring IOC系列学习笔记二:obtainFreshBeanFactory方法
Spring IOC系列学习笔记三:parseDefaultElement详解
Spring IOC系列学习笔记四:parseCustomElement解析
Spring IOC系列学习笔记五:context:component-scan 节点解析
Spring IOC系列学习笔记六:invokeBeanFactoryPostProcessors解析
Spring IOC系列学习笔记七:registerBeanPostProcessors
Spring IOC系列学习笔记八:finishBeanFactoryInitialization
Spring IOC系列学习笔记九:getBean方法
Spring IOC系列学习笔记十:createBean方法(上)
Spring IOC系列学习笔记十一:createBean方法(下)
Spring IOC系列学习笔记十二:@Autowire注解


前言

继续Spring系列学习笔记二:obtainFreshBeanFactory方法的讲解,下面我们进入对默认的命名空间的处理,进入parseDefaultElement方法中。


代码块一:parseDefaultElement

	private void parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate) {
		1、解析import节点
		if (delegate.nodeNameEquals(ele, IMPORT_ELEMENT)) {
			importBeanDefinitionResource(ele);
		}
		2、解析alias节点
		else if (delegate.nodeNameEquals(ele, ALIAS_ELEMENT)) {
			processAliasRegistration(ele);
		}
		3、解析bean节点
		else if (delegate.nodeNameEquals(ele, BEAN_ELEMENT)) {
			processBeanDefinition(ele, delegate);
		}
		4、解析beans节点
		else if (delegate.nodeNameEquals(ele, NESTED_BEANS_ELEMENT)) {
			doRegisterBeanDefinitions(ele);
		}
	}

可以看到默认的命名空间一共有四个标签,分别是bean、import、beans、alias标签。我们只介绍bean标签这个是比较复杂的其他的就比较好理解了。
3、解析bean节点 见代码块二

代码块二:processBeanDefinition

	protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
		1、解析bean节点,bdHolder包含了该节点的BeanDefinition,name,和alias。
		BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
		if (bdHolder != null) {
			2、注册自定义的标签, 比如这个就是自定义标签
			//<bean id="animal" class="test.constructor.Animal">
       		//<myTag:my   value="p1"/> 
   			// </bean>
			bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);
			try {
				// Register the final decorated instance.
				3、注册bdHolder
				BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry());
			}
			catch (BeanDefinitionStoreException ex) {
				getReaderContext().error("Failed to register bean definition with name '" +
						bdHolder.getBeanName() + "'", ele, ex);
			}
			// Send registration event.
			4、发出响应事件表示该bean已经注册完成
			getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder));
		}
	}

1、解析bean节点见代码块三
3、注册bean见代码块代码块十四

代码块三:parseBeanDefinitionElement

	@Nullable
	public BeanDefinitionHolder parseBeanDefinitionElement(Element ele, @Nullable BeanDefinition containingBean) {
		11获取id属性
		String id = ele.getAttribute(ID_ATTRIBUTE);
		1.2、获取name属性
		String nameAttr = ele.getAttribute(NAME_ATTRIBUTE);

		List<String> aliases = new ArrayList<>();
		if (StringUtils.hasLength(nameAttr)) {
			1.3、分割nameArr字符,可能取了几个别名
			String[] nameArr = StringUtils.tokenizeToStringArray(nameAttr, MULTI_VALUE_ATTRIBUTE_DELIMITERS);
			aliases.addAll(Arrays.asList(nameArr));
		}

		String beanName = id;
		1.4、如果没指定id,则指定name的第一个为别名
		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) {
			2、检查当前bean的名字在同一个<beans>下是否已经存在
			checkNameUniqueness(beanName, aliases, ele);
		}
		3、解析bean节点
		AbstractBeanDefinition beanDefinition = parseBeanDefinitionElement(ele, beanName, containingBean);
		if (beanDefinition != null) {
			4、如果既没有指定name也没有指定id则进入
			if (!StringUtils.hasText(beanName)) {
				try {
					if (containingBean != null) {
						4.1如果bean定义已经存在,则这种规则生成一个bean的名字
						beanName = BeanDefinitionReaderUtils.generateBeanName(
								beanDefinition, this.readerContext.getRegistry(), true);
					}
					else {
						4.2如果bean定义不存在,则由spring提供的规则生成
						beanName = this.readerContext.generateBeanName(beanDefinition);
						// Register an alias for the plain bean class name, if still possible,
						// if the generator returned the class name plus a suffix.
						// This is expected for Spring 1.2/2.0 backwards compatibility.
						String beanClassName = beanDefinition.getBeanClassName();
						if (beanClassName != null &&
								beanName.startsWith(beanClassName) && beanName.length() > beanClassName.length() &&
								!this.readerContext.getRegistry().isBeanNameInUse(beanClassName)) {
							4.3将该类名注册为别名
							aliases.add(beanClassName);
						}
					}
					if (logger.isDebugEnabled()) {
						logger.debug("Neither XML 'id' nor 'name' specified - " +
								"using generated bean name [" + beanName + "]");
					}
				}
				catch (Exception ex) {	
					error(ex.getMessage(), ele);
					return null;
				}
			}
			String[] aliasesArray = StringUtils.toStringArray(aliases);
			5.封装成BeanDefinitionHolder		
			return new BeanDefinitionHolder(beanDefinition, beanName, aliasesArray);
		}

		return null;
	}

3、解析bean节点见代码块四

代码块四:parseBeanDefinitionElement

@Nullable
	public AbstractBeanDefinition parseBeanDefinitionElement(
			Element ele, String beanName, @Nullable BeanDefinition containingBean) {
		1、一个标志代表解析已经开始了 最后会移除
		this.parseState.push(new BeanEntry(beanName));

		String className = null;
		2、获取calss属性
		if (ele.hasAttribute(CLASS_ATTRIBUTE)) {
			className = ele.getAttribute(CLASS_ATTRIBUTE).trim();
		}
		String parent = null;
		2.1获取parent属性
		if (ele.hasAttribute(PARENT_ATTRIBUTE)) {
			parent = ele.getAttribute(PARENT_ATTRIBUTE);
		}

		try {
			3、根据class和parent创建一个AbstractBeanDefinitionAbstractBeanDefinition bd = createBeanDefinition(className, parent);
			4、解析bean标签的属性
			parseBeanDefinitionAttributes(ele, beanName, containingBean, bd);
			bd.setDescription(DomUtils.getChildElementValueByTagName(ele, DESCRIPTION_ELEMENT));
			5、解析<meta>
			parseMetaElements(ele, bd);
			6、解析<lookup-method>
			parseLookupOverrideSubElements(ele, bd.getMethodOverrides());
			7、解析<replaced-method>
			parseReplacedMethodSubElements(ele, bd.getMethodOverrides());
			8、解析 <constructor-arg>
			parseConstructorArgElements(ele, bd);
			9、解析<property>
			parsePropertyElements(ele, bd);
			10、解析<qualifier>
			parseQualifierElements(ele, bd);

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

			return bd;
		}
		catch (ClassNotFoundException ex) {
			error("Bean class [" + className + "] not found", ele, ex);
		}
		catch (NoClassDefFoundError err) {
			error("Class that bean class [" + className + "] depends on not found", ele, err);
		}
		catch (Throwable ex) {
			error("Unexpected failure during bean definition parsing", ele, ex);
		}
		finally {
			this.parseState.pop();
		}

		return null;
	}

3、直接new GenericBeanDefinition比较简单,然后根据className和classLoader判断是否通过反射出一个实例并添加到GenericBeanDefinition中。
4、解析bean标签的属性见代码块五
8、解析 见代码块六
9、解析见代码块十三

代码块五:parseBeanDefinitionAttributes

	public AbstractBeanDefinition parseBeanDefinitionAttributes(Element ele, String beanName,
			@Nullable BeanDefinition containingBean, AbstractBeanDefinition bd) {
		1.1、新版本已经不用singleton属性 如果有则抛出异常
		if (ele.hasAttribute(SINGLETON_ATTRIBUTE)) {
			error("Old 1.x 'singleton' attribute in use - upgrade to 'scope' declaration", ele);
		}
		1.2、 设置scope属性
		else if (ele.hasAttribute(SCOPE_ATTRIBUTE)) {
			bd.setScope(ele.getAttribute(SCOPE_ATTRIBUTE));
		}

		else if (containingBean != null) {
			// Take default from containing bean in case of an inner bean definition.
			bd.setScope(containingBean.getScope());
		}
		2、设置abstract属性
		if (ele.hasAttribute(ABSTRACT_ATTRIBUTE)) {
			bd.setAbstract(TRUE_VALUE.equals(ele.getAttribute(ABSTRACT_ATTRIBUTE)));
		}
		3、设置lazy-init属性
		String lazyInit = ele.getAttribute(LAZY_INIT_ATTRIBUTE);
		if (DEFAULT_VALUE.equals(lazyInit)) {
			lazyInit = this.defaults.getLazyInit();
		}
	
		bd.setLazyInit(TRUE_VALUE.equals(lazyInit));
		4、设置autowire属性
		String autowire = ele.getAttribute(AUTOWIRE_ATTRIBUTE);
		
		bd.setAutowireMode(getAutowireMode(autowire));
		5、设置depends-on属性
		if (ele.hasAttribute(DEPENDS_ON_ATTRIBUTE)) {
			String dependsOn = ele.getAttribute(DEPENDS_ON_ATTRIBUTE);
			bd.setDependsOn(StringUtils.tokenizeToStringArray(dependsOn, MULTI_VALUE_ATTRIBUTE_DELIMITERS));
		}
		6、设置autowire-candidate属性
		String autowireCandidate = ele.getAttribute(AUTOWIRE_CANDIDATE_ATTRIBUTE);
		if ("".equals(autowireCandidate) || DEFAULT_VALUE.equals(autowireCandidate)) {
			String candidatePattern = this.defaults.getAutowireCandidates();
			if (candidatePattern != null) {
				String[] patterns = StringUtils.commaDelimitedListToStringArray(candidatePattern);
				
				bd.setAutowireCandidate(PatternMatchUtils.simpleMatch(patterns, beanName));
			}
		}
		else {
			bd.setAutowireCandidate(TRUE_VALUE.equals(autowireCandidate));
		}
		7、设置primary属性
		if (ele.hasAttribute(PRIMARY_ATTRIBUTE)) {
			bd.setPrimary(TRUE_VALUE.equals(ele.getAttribute(PRIMARY_ATTRIBUTE)));
		}
		8、设置init-method属性
		if (ele.hasAttribute(INIT_METHOD_ATTRIBUTE)) {
			String initMethodName = ele.getAttribute(INIT_METHOD_ATTRIBUTE);
			bd.setInitMethodName(initMethodName);
		}
		else if (this.defaults.getInitMethod() != null) {
			bd.setInitMethodName(this.defaults.getInitMethod());
			bd.setEnforceInitMethod(false);
		}
		9、设置destroy-method属性
		if (ele.hasAttribute(DESTROY_METHOD_ATTRIBUTE)) {
			String destroyMethodName = ele.getAttribute(DESTROY_METHOD_ATTRIBUTE);
			bd.setDestroyMethodName(destroyMethodName);
		}
		else if (this.defaults.getDestroyMethod() != null) {
			bd.setDestroyMethodName(this.defaults.getDestroyMethod());
			bd.setEnforceDestroyMethod(false);
		}
		10、设置factory-method属性
		if (ele.hasAttribute(FACTORY_METHOD_ATTRIBUTE)) {
			bd.setFactoryMethodName(ele.getAttribute(FACTORY_METHOD_ATTRIBUTE));
		}
		11、设置factory-bean属性
		if (ele.hasAttribute(FACTORY_BEAN_ATTRIBUTE)) {
			bd.setFactoryBeanName(ele.getAttribute(FACTORY_BEAN_ATTRIBUTE));
		}

		return bd;
	}

代码块六:parseConstructorArgElements

	public void parseConstructorArgElements(Element beanEle, BeanDefinition bd) {
		1、拿到所有子节点
		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)) {
			2、解析constructor-arg节点
				parseConstructorArgElement((Element) node, bd);
			}
		}
	}

2、解析constructor-arg节点见代码块七

代码块七:parseConstructorArgElement

	public void parseConstructorArgElement(Element ele, BeanDefinition bd) {
		1.1、获取index属性
		String indexAttr = ele.getAttribute(INDEX_ATTRIBUTE);
		1.2、获取type属性
		String typeAttr = ele.getAttribute(TYPE_ATTRIBUTE);
		1.2获取name属性
		String nameAttr = ele.getAttribute(NAME_ATTRIBUTE);
		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));
						2、解析属性值 包括子节点的
						Object value = parsePropertyValue(ele, bd, null);
						2.1、解析后的数据封装到ConstructorArgumentValues.ValueHolderConstructorArgumentValues.ValueHolder valueHolder = new ConstructorArgumentValues.ValueHolder(value);
						if (StringUtils.hasLength(typeAttr)) {
							2.2、设置type属性
							valueHolder.setType(typeAttr);
						}
						if (StringUtils.hasLength(nameAttr)) {
							2.3、设置name属性
							valueHolder.setName(nameAttr);
						}
						valueHolder.setSource(extractSource(ele));
						2.4判断index是否重复
						if (bd.getConstructorArgumentValues().hasIndexedArgumentValue(index)) {
							error("Ambiguous constructor-arg entries for index " + index, ele);
						}
						else {
							// 将index和valueHolder以key-value形式添加至当前BeanDefinition的constructorArgumentValues
                       		// 的indexedArgumentValues属性中,(用于上面判断index是否重复指定)
							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 {
			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));
				3、与上面的indexedArgumentValues类似,上面有index存为map,这边没index存为list
				bd.getConstructorArgumentValues().addGenericArgumentValue(valueHolder);
			}
			finally {
				this.parseState.pop();
			}
		}
	}

1.1先获取index、type、name的属性
2解析属性值 ref、value、list肯定包含其中一个见代码块八
2.4判断index是否重复,不重复则将 index 和 valueHolder 以 key-value 形式添加至当前BeanDefinition 的 constructorArgumentValues 的 indexedArgumentValues 属性中 。

代码块八:parsePropertyValue

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

		// Should only have one child element: ref, value, list, etc.
		// 应该只有 ref, value, list三个的其中一个
		1、获取子节点 list、map等
		NodeList nl = ele.getChildNodes();
		Element subElement = null;
		for (int i = 0; i < nl.getLength(); i++) {
			Node node = nl.item(i);
			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 {
					1.1、找到子节点,赋值给subElement
					subElement = (Element) node;
				}
			}
		}
		2.1、判断是ref吗
		boolean hasRefAttribute = ele.hasAttribute(REF_ATTRIBUTE);
		2.2、判断是value吗
		boolean hasValueAttribute = ele.hasAttribute(VALUE_ATTRIBUTE);
		2.3、不能同时存在,如果同时存在直接抛出异常
		if ((hasRefAttribute && hasValueAttribute) ||
				((hasRefAttribute || hasValueAttribute) && subElement != null)) {
			error(elementName +
					" is only allowed to contain either 'ref' attribute OR 'value' attribute OR sub-element", ele);
		}

		if (hasRefAttribute) {
			3、处理ref属性,把它放到RuntimeBeanReference,相当于一个临时的容器当我们用的时候去解析成真正的bean实例。
			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;
		}
		else if (hasValueAttribute) {
			4、处理value属性,用TypedStringValue封装
			TypedStringValue valueHolder = new TypedStringValue(ele.getAttribute(VALUE_ATTRIBUTE));
			valueHolder.setSource(extractSource(ele));
			return valueHolder;
		}
		else if (subElement != null) {
			5、解析子节点 如list
			return parsePropertySubElement(subElement, bd);
		}
		else {
			6、都没有就直接抛出异常
			// Neither child element nor "ref" or "value" attribute found.
			error(elementName + " must specify a ref or value", ele);
			return null;
		}
	}

先解析属性值,value或ref属性,如果没有解析子节点。
5、解析子节点见代码块九

代码块九:parsePropertySubElement

	@Nullable
	public Object parsePropertySubElement(Element ele, @Nullable BeanDefinition bd) {
		return parsePropertySubElement(ele, bd, null);
	}

	
	@Nullable
	public Object parsePropertySubElement(Element ele, @Nullable BeanDefinition bd, @Nullable String defaultValueType) {
		1、如果不是默认的命名空间就去定制方法进行解析
		if (!isDefaultNamespace(ele)) {
			return parseNestedCustomElement(ele, bd);
		}
		else if (nodeNameEquals(ele, BEAN_ELEMENT)) {
			2、子节点是bean会递归解析bean的方法
			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.
			3、子节点是ref会和处理属性一样封装到临时的RuntimeBeanReference在真正解析的时候实例化。
			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.
				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;
		}
		else if (nodeNameEquals(ele, IDREF_ELEMENT)) {
			4、解析idref
			return parseIdRefElement(ele);
		}
		else if (nodeNameEquals(ele, VALUE_ELEMENT)) {
			5、解析value
			return parseValueElement(ele, defaultValueType);
		}
		else if (nodeNameEquals(ele, NULL_ELEMENT)) {
			6、直接设置为null返回
			// 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)) {
			7、解析array
			return parseArrayElement(ele, bd);
		}
		else if (nodeNameEquals(ele, LIST_ELEMENT)) {
			8、解析list
			return parseListElement(ele, bd);
		}
		else if (nodeNameEquals(ele, SET_ELEMENT)) {
			9、解析set
			return parseSetElement(ele, bd);
		}
		else if (nodeNameEquals(ele, MAP_ELEMENT)) {
			10、解析map
			return parseMapElement(ele, bd);
		}
		else if (nodeNameEquals(ele, PROPS_ELEMENT)) {
			11、解析prop
			return parsePropsElement(ele);
		}
		else {
			12、都没有抛出异常
			error("Unknown property sub-element: [" + ele.getNodeName() + "]", ele);
			return null;
		}
	}

2、解析bean节点前面已经介绍过了见代码块四
5、解析value节点见代码块十
8、解析list节点见代码块十二

代码块十:parseValueElement

	public Object parseValueElement(Element ele, @Nullable String defaultTypeName) {
		// It's a literal value.
		String value = DomUtils.getTextValue(ele);
		String specifiedTypeName = ele.getAttribute(TYPE_ATTRIBUTE);
		String typeName = specifiedTypeName;
		if (!StringUtils.hasText(typeName)) {
			//如果没有就用默认的类型
			typeName = defaultTypeName;
		}
		try {
			1、构建TypedStringValue
			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;
		}
	}

1、构建TypedStringValue见代码块十一

代码块十一:buildTypedStringValue

	protected TypedStringValue buildTypedStringValue(String value, @Nullable String targetTypeName)
			throws ClassNotFoundException {

		ClassLoader classLoader = this.readerContext.getBeanClassLoader();
		TypedStringValue typedValue;
		if (!StringUtils.hasText(targetTypeName)) {
			1、如果没有设置类型直接new
			typedValue = new TypedStringValue(value);
		}
		else if (classLoader != null) {
			2、类加载器和targetTypeName不为空,通过反射创建该类型的类
			Class<?> targetType = ClassUtils.forName(targetTypeName, classLoader);
			typedValue = new TypedStringValue(value, targetType);
		}
		else {
			3、使用value 和 type来构建
			typedValue = new TypedStringValue(value, targetTypeName);
		}
		return typedValue;
	}

代码块十二:parseListElement

	public List<Object> parseListElement(Element collectionEle, @Nullable BeanDefinition bd) {
		1、获取list的value-type属性,就是list节点下value的类型
		String defaultElementType = collectionEle.getAttribute(VALUE_TYPE_ATTRIBUTE);
		2、获取所有的子节点,一般为value
		NodeList nl = collectionEle.getChildNodes();
		3、用来存放节点的值
		ManagedList<Object> target = new ManagedList<>(nl.getLength());
		target.setSource(extractSource(collectionEle));
		target.setElementTypeName(defaultElementType);
		target.setMergeEnabled(parseMergeAttribute(collectionEle));
		4、解析子节点集合
		parseCollectionElements(nl, target, bd, defaultElementType);
		return target;
	}


	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);
			if (node instanceof Element && !nodeNameEquals(node, DESCRIPTION_ELEMENT)) {
				5、递归的去解析子节点的方法 这儿一般会进入解析value的方法
				target.add(parsePropertySubElement((Element) node, bd, defaultElementType));
			}
		}
	}

到这儿 constructor-arg已经解析完毕,回到代码块四继续解析。

代码块十三: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)) {
				1、  解析property节点
				parsePropertyElement((Element) node, bd);
			}
		}
	}


	public void parsePropertyElement(Element ele, BeanDefinition bd) {
		1、获取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 {
			//校验在相同bean节点下,是否存在相同的name属性,如果存在则抛出异常
			if (bd.getPropertyValues().contains(propertyName)) {
				error("Multiple 'property' definitions for property '" + propertyName + "'", ele);
				return;
			}
			2、解析属性 见代码块八
			Object val = parsePropertyValue(ele, bd, propertyName);
			PropertyValue pv = new PropertyValue(propertyName, val);
			3、解析meta属性
			parseMetaElements(ele, pv);
			pv.setSource(extractSource(ele));
			//用于重复校验
			bd.getPropertyValues().addPropertyValue(pv);
		}
		finally {
			this.parseState.pop();
		}
	}

2、解析属性见代码块八
我们回到代码块二继续讲解开始进入registerBeanDefinition方法。

代码块十四:registerBeanDefinition

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

		// Register bean definition under primary name.
		1、获取要注册的name
		String beanName = definitionHolder.getBeanName();
		2、注册beanName、BeanDefinition到缓存中(核心逻辑),实现类为; DefaultListableBeanFactory
		registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());

		// Register aliases for bean name, if any.
		String[] aliases = definitionHolder.getAliases();
		if (aliases != null) {
			for (String alias : aliases) {
			3、注册别名到aliasMap缓存中
				registry.registerAlias(beanName, alias);
			}
		}
	}

2、注册beanName、BeanDefinition到缓存中见代码块十五
3、注册别名见代码块十六

代码块十五:registerBeanDefinition

@Override
	public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
			throws BeanDefinitionStoreException {
		1.beanName和beanDefinition为空校验
		Assert.hasText(beanName, "Bean name must not be empty");
		Assert.notNull(beanDefinition, "BeanDefinition must not be null");

		if (beanDefinition instanceof AbstractBeanDefinition) {
			try {
				((AbstractBeanDefinition) beanDefinition).validate();
			}
			catch (BeanDefinitionValidationException ex) {
				throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,
						"Validation of bean definition failed", ex);
			}
		}

		BeanDefinition oldBeanDefinition;
		2、先尝试从缓存中获取
		oldBeanDefinition = this.beanDefinitionMap.get(beanName);

		if (oldBeanDefinition != null) {
			if (!isAllowBeanDefinitionOverriding()) {
				2.1、不允许注册相同名字的bean则直接抛出异常
				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 (!beanDefinition.equals(oldBeanDefinition)) {
				if (this.logger.isInfoEnabled()) {
					this.logger.info("Overriding bean definition for bean '" + beanName +
							"' with a different definition: replacing [" + oldBeanDefinition +
							"] with [" + beanDefinition + "]");
				}
			}
			else {
				if (this.logger.isDebugEnabled()) {
					this.logger.debug("Overriding bean definition for bean '" + beanName +
							"' with an equivalent definition: replacing [" + oldBeanDefinition +
							"] with [" + beanDefinition + "]");
				}
			}
			2.2、放到缓存当中
			this.beanDefinitionMap.put(beanName, beanDefinition);
		}
		else {
			3、是否已经开始创建
			if (hasBeanCreationStarted()) {
				// Cannot modify startup-time collection elements anymore (for stable iteration)
				synchronized (this.beanDefinitionMap) {
					3.1、已经开始了,将beanName和beanDefinition放到map缓存当中,就是开始我们提到的重要缓存之一。
					this.beanDefinitionMap.put(beanName, beanDefinition);

					List<String> updatedDefinitions = new ArrayList<>(this.beanDefinitionNames.size() + 1);
					updatedDefinitions.addAll(this.beanDefinitionNames);
					updatedDefinitions.add(beanName);
					this.beanDefinitionNames = updatedDefinitions;
					if (this.manualSingletonNames.contains(beanName)) {
						3.2、因为已经创建好了,所以把排序的manualSingletonNames移除beanName
						Set<String> updatedSingletons = new LinkedHashSet<>(this.manualSingletonNames);
						updatedSingletons.remove(beanName);
						this.manualSingletonNames = updatedSingletons;
					}
				}
			}
			else {
				// Still in startup registration phase
				4、未开始直接放到缓存当中
				this.beanDefinitionMap.put(beanName, beanDefinition);
				this.beanDefinitionNames.add(beanName);
				this.manualSingletonNames.remove(beanName);
			}
			this.frozenBeanDefinitionNames = null;
		}

		if (oldBeanDefinition != null || containsSingleton(beanName)) {
			resetBeanDefinition(beanName);
		}
	}

到这儿注册完成,注册其实就是放到缓存当中,等需要实例的时候从缓存中获取然后利用反射进行实例化。回到代码块十四进入注册别名方法。

代码块十六:registerAlias

@Override
public void registerAlias(String name, String alias) {
    Assert.hasText(name, "'name' must not be empty");
    Assert.hasText(alias, "'alias' must not be empty");
    // 1.如果别名和beanName相同,则不算别名,从aliasMap缓存中移除
    if (alias.equals(name)) {
        this.aliasMap.remove(alias);
    }
    else {
        String registeredName = this.aliasMap.get(alias);
        if (registeredName != null) {
            if (registeredName.equals(name)) {
                // An existing alias - no need to re-register
                // 2.如果别名已经注册过,直接返回
                return;
            }
            // 3.如果存在相同的别名,并且不允许别名覆盖,则抛出异常
            if (!allowAliasOverriding()) {
                throw new IllegalStateException("Cannot register alias '" + alias + "' for name '" +
                        name + "': It is already registered for name '" + registeredName + "'.");
            }
        }
        // 4.检查name和alias是否存在循环引用。例如A的别名为B,B的别名为A
        checkForAliasCircle(name, alias);
        // 5.将别名和beanName的映射放到aliasMap缓存中
        this.aliasMap.put(alias, name);
    }
}

总结

我们可以重新梳理一下思路,我们首先将 xml 中的 bean 配置信息进行了解析,并构建了 AbstractBeanDefinition(GenericBeanDefinition) 对象来存放所有解析出来的属性。

然后,我们将 AbstractBeanDefinition 、beanName、aliasesArray 构建成 BeanDefinitionHolder 对象并返回。

最后,我们通过 BeanDefinitionHolder 将 BeanDefinition 和 beanName 注册到 BeanFactory 中,也就是存放到缓存中。

执行完 parseDefaultElement 方法,我们得到了两个重要的缓存:

beanDefinitionNames 缓存。
beanDefinitionMap 缓存。
这两个缓存在之后的 IoC 构建过程中会发挥很重要的作用,大家在这边先有个印象。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值
>