四、Spring默认标签之bean标签的解析及注册

一、先期准备

参见 三、Spring之解析及注册 BeanDefinitions 之默认标签的解析

二、bean 标签的解析及注册

(一)调用流程

  1. 首先委托 BeanDefinitionParserDelegate 类的 parseBeanDefinitionElement() 方法进行元素解析,返回 BeanDefinitionHolder 类型的实例 bdHolder,经过这个方法以后,bdHolder 实例已经包含我们配置文件中配置的各种属性了,例如 class、name、id、alias 之类的属性
  2. 当返回的 bdHolder 不为空的情况下若存在默认标签的子节点下再有自定义属性,还需要再次对自定义标签进行解析
  3. 解析完成以后,需要对解析后的 bdHolder 进行注册,同样,注册委托给了 BeanDefinitionReaderUtilsregisterBeanDefinition() 方法
  4. 最后发出响应事件,通知相关的监听器,这个 bean 已经加载完成
	protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
		/*
		 *    首先委托 BeanDefinitionParserDelegate 类的 parseBeanDefinitionElement() 方法进行元素解析,返回
		 * BeanDefinitionHolder 类型的实例 bdHolder,经过这个方法以后,bdHolder 实例已经包含我们配置文件中配
		 * 置的各种属性了,例如 class、name、id、alias 之类的属性
		 */
		BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
		if (bdHolder != null) {
			/*
			 *     当返回的 bdHolder 不为空的情况下若存在默认标签的子节点下再有自定义属性,还需要再次对自定义标签进行
			 * 解析
			 */
			bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);
			try {
				// Register the final decorated instance.
				/*
				 *     解析完成以后,需要对解析后的 bdHolder 进行注册,同样,注册委托给了 BeanDefinitionReaderUtils 的
				 * registerBeanDefinition() 方法
				 */
				BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry());
			}
			catch (BeanDefinitionStoreException ex) {
				getReaderContext().error("Failed to register bean definition with name '" +
						bdHolder.getBeanName() + "'", ele, ex);
			}
			// Send registration event.
			/*
			 *     最后发出响应事件,通知相关的监听器,这个 bean 已经加载完成
			 */
			getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder));
		}
	}
  • BeanDefinitionParserDelegate#parseBeanDefinitionElement(Element ele, @Nullable BeanDefinition containingBean)
  1. 抽取元素中的 id 以及 name 属性
  2. 进一步解析其他所有属性并统一封装至 GenericBeanDefinition 类型的实例中
  3. 如果检测到 bean 没有指定 beanName,那么使用默认规则为此 Bean 生成 beanName
  4. 将获取到的信息封装到 BeanDefinitionHolder
	/**
	 * 主要是对属性 id 以及 name 的解析:
	 * 1.抽取元素中的 id 以及 name 属性
	 * 2.进一步解析其他所有属性并统一封装至 GenericBeanDefinition 类型的实例中
	 * 3.如果检测到 bean 没有指定 beanName,那么使用默认规则为此 Bean 生成 beanName
	 * 4.将获取到的信息封装到 BeanDefinitionHolder 中
	 */
	@Nullable
	public BeanDefinitionHolder parseBeanDefinitionElement(Element ele, @Nullable BeanDefinition containingBean) {
		// 解析 id 属性
		String id = ele.getAttribute(ID_ATTRIBUTE);
		// 解析 name 属性
		String nameAttr = ele.getAttribute(NAME_ATTRIBUTE);

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

		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) {
			checkNameUniqueness(beanName, aliases, ele);
		}
		// 解析其他所有子元素,诸如:meta、lookup-method、replaced-method、constructor-arg、property、qualifier
		AbstractBeanDefinition beanDefinition = parseBeanDefinitionElement(ele, beanName, containingBean);

		if (beanDefinition != null) {
			// 若不存在 beanName 那么根据 Spring 中提供的命名规则为当前 bean 生成对应的 beanName
			if (!StringUtils.hasText(beanName)) {
				try {
					if (containingBean != null) {
						beanName = BeanDefinitionReaderUtils.generateBeanName(
								beanDefinition, this.readerContext.getRegistry(), true);
					}
					else {
						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)) {
							aliases.add(beanClassName);
						}
					}
					if (logger.isTraceEnabled()) {
						logger.trace("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);
			return new BeanDefinitionHolder(beanDefinition, beanName, aliasesArray);
		}

		return null;
	}
  • BeanDefinitionParserDelegate#parseBeanDefinitionElement(Element ele, String beanName, @Nullable BeanDefinition containingBean)
  1. 创建用于承载属性的 AbstractBeanDefinition 类型的 GenericBeanDefinition
  2. 硬编码解析默认 <bean> 标签的各种属性
  3. 解析子元素 meta
  4. 解析子元素 lookup-method
  5. 解析子元素 replaced-method
  6. 解析子元素 constructor-arg
  7. 解析子元素 property
  8. 解析子元素 qualifier

	@Nullable
	public AbstractBeanDefinition parseBeanDefinitionElement(
			Element ele, String beanName, @Nullable BeanDefinition containingBean) {

		this.parseState.push(new BeanEntry(beanName));

		String className = null;
		// 解析 class 属性
		if (ele.hasAttribute(CLASS_ATTRIBUTE)) {
			className = ele.getAttribute(CLASS_ATTRIBUTE).trim();
		}
		String parent = null;
		// 解析 parent 属性
		if (ele.hasAttribute(PARENT_ATTRIBUTE)) {
			parent = ele.getAttribute(PARENT_ATTRIBUTE);
		}

		try {
			/*
			 * 创建用于承载属性的 AbstractBeanDefinition 类型的 GenericBeanDefinition:
			 *     BeanDefinition 是一个接口,在 Spring 中存在三种实现:RootBeanDefinition、ChildBeanDefinition 以及
			 * GenericBeanDefinition 。三种实现均继承了 AbstractBeanDefinition ,其中 BeanDefinition 是配置文件 <bean>
			 * 元素标签在容器中的内部表现形式。<bean> 元素标签拥有 class、scope、lazy-init 等配置属性,BeanDefinition则
			 * 提供了相应的 beanClass、scope、lazyInit 属性,BeanDefinition 和 <bean> 中的属性是一一对应的。
			 */
			AbstractBeanDefinition bd = createBeanDefinition(className, parent);
			// 硬编码解析默认 <bean>标签的各种属性
			parseBeanDefinitionAttributes(ele, beanName, containingBean, bd);
			// 提取 description
			bd.setDescription(DomUtils.getChildElementValueByTagName(ele, DESCRIPTION_ELEMENT));

			//解析元数据
			parseMetaElements(ele, bd);
			/*
			 * 解析 lookup-method 属性:
			 *     我们通常称 lookup-method 为获取器注入,获取注入是一种特殊的方法注入,它是把一个方法声明为返回某种类型
			 * 的 bean,但实际要返回的 bean 是在配置文件里面配置的,此方法可用在设计有些可插拔的功能上,解除程序依赖。
			 * 案例参见书本 P53-54
			 */
			parseLookupOverrideSubElements(ele, bd.getMethodOverrides());
			/*
			 * 解析 replaced-method 属性:
			 *     方法替换:可以在运行时用心得的方法替换现有的方法。与之前的 look-up 不同的是,replaced-method 不但可以
			 * 动态地替换返回实体 bean,而且还能动态地更改原有方法的逻辑。案例参见书本 P55-56
			 */
			parseReplacedMethodSubElements(ele, bd.getMethodOverrides());

			//解析构造函数参数
			parseConstructorArgElements(ele, bd);
			//解析 property 子元素
			parsePropertyElements(ele, bd);
			//解析 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;
	}
  • BeanDefinitionParserDelegate#createBeanDefinition(@Nullable String className, @Nullable String parentName)
	/*
	 * 创建用于承载属性的 AbstractBeanDefinition 类型的 GenericBeanDefinition:
	 *     BeanDefinition 是一个接口,在 Spring 中存在三种实现:RootBeanDefinition、ChildBeanDefinition 以及
	 * GenericBeanDefinition 。三种实现均继承了 AbstractBeanDefinition ,其中 BeanDefinition 是配置文件 <bean>
	 * 元素标签在容器中的内部表现形式。<bean> 元素标签拥有 class、scope、lazy-init 等配置属性,BeanDefinition则
	 * 提供了相应的 beanClass、scope、lazyInit 属性,BeanDefinition 和 <bean> 中的属性是一一对应的。
	 */
	public static AbstractBeanDefinition createBeanDefinition(
			@Nullable String parentName, @Nullable String className, @Nullable ClassLoader classLoader) throws ClassNotFoundException {

		GenericBeanDefinition bd = new GenericBeanDefinition();
		bd.setParentName(parentName);
		if (className != null) {
			if (classLoader != null) {
				// 若 classLoader 不为空,则使用已传入的 classLoader 同一虚拟机加载类对象,否则只是记录 className
				bd.setBeanClass(ClassUtils.forName(className, classLoader));
			}
			else {
				bd.setBeanClassName(className);
			}
		}
		return bd;
	}
  • BeanDefinitionParserDelegate#parseBeanDefinitionAttributes(Element ele, String beanName,@Nullable BeanDefinition containingBean, AbstractBeanDefinition bd)
	/**
	 * 对 <bean> 标签的所有属性进行解析,例如:scope、lazy-init 等
	 */
	public AbstractBeanDefinition parseBeanDefinitionAttributes(Element ele, String beanName,
			@Nullable BeanDefinition containingBean, AbstractBeanDefinition bd) {

		if (ele.hasAttribute(SINGLETON_ATTRIBUTE)) {
			// singleton 属性已不再使用,改为 scope 属性
			error("Old 1.x 'singleton' attribute in use - upgrade to 'scope' declaration", ele);
		}
		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.
			// 在嵌入 BeanDefinition 情况下且没有单独指定 scope 属性则使用父类默认的属性
			bd.setScope(containingBean.getScope());
		}

		// 解析 abstract 属性
		if (ele.hasAttribute(ABSTRACT_ATTRIBUTE)) {
			bd.setAbstract(TRUE_VALUE.equals(ele.getAttribute(ABSTRACT_ATTRIBUTE)));
		}

		// 解析 lazy-init 属性,若没有设置或者设置成其他字符都会被设置为 false
		String lazyInit = ele.getAttribute(LAZY_INIT_ATTRIBUTE);
		if (isDefaultValue(lazyInit)) {
			lazyInit = this.defaults.getLazyInit();
		}
		bd.setLazyInit(TRUE_VALUE.equals(lazyInit));

		// 解析 autowire 属性
		String autowire = ele.getAttribute(AUTOWIRE_ATTRIBUTE);
		bd.setAutowireMode(getAutowireMode(autowire));

		// 解析 depends-on 属性(depends-on用来指定Bean初始化及销毁时的顺序)
		if (ele.hasAttribute(DEPENDS_ON_ATTRIBUTE)) {
			String dependsOn = ele.getAttribute(DEPENDS_ON_ATTRIBUTE);
			bd.setDependsOn(StringUtils.tokenizeToStringArray(dependsOn, MULTI_VALUE_ATTRIBUTE_DELIMITERS));
		}

		/*
		 * 解析 autowire-candidate 属性:
		 *     自动依赖注入大大简化了我们的工作量,但是也有缺陷,如果一个接口有多个实现类,我们该注入哪一个呢?
		 *     一种方法是设置其中一个bean不参与自动注入:<bean class="shangbo.spring.example38.MessageServiceDBImpl" autowire-candidate="false" />
		 *     另一种方法是全局设定哪些对象不参数自动注入:
		 *     <beans xmlns="http://www.springframework.org/schema/beans"
    			xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    			xsi:schemaLocation="http://www.springframework.org/schema/beans
				http://www.springframework.org/schema/beans/spring-beans.xsd"
				default-autowire="byType"
				default-autowire-candidates="messageServiceDBImpl">
		 */
		String autowireCandidate = ele.getAttribute(AUTOWIRE_CANDIDATE_ATTRIBUTE);
		if (isDefaultValue(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));
		}

		// 解析 primary 属性
		if (ele.hasAttribute(PRIMARY_ATTRIBUTE)) {
			bd.setPrimary(TRUE_VALUE.equals(ele.getAttribute(PRIMARY_ATTRIBUTE)));
		}
		// 解析 init-method 属性(相当于 @PostConstruct 注解)
		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);
		}

		// 解析 destroy-method 属性(相当于 @PreDestroy 注解)
		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);
		}

		// 解析 factory-method 属性(详情解析参见:https://blog.csdn.net/qq_33188563/article/details/82865165)
		if (ele.hasAttribute(FACTORY_METHOD_ATTRIBUTE)) {
			bd.setFactoryMethodName(ele.getAttribute(FACTORY_METHOD_ATTRIBUTE));
		}
		// 解析 factory-bean 属性(详情解析参见:https://blog.csdn.net/qq_33188563/article/details/82865165)
		if (ele.hasAttribute(FACTORY_BEAN_ATTRIBUTE)) {
			bd.setFactoryBeanName(ele.getAttribute(FACTORY_BEAN_ATTRIBUTE));
		}

		return bd;
	}
  • BeanDefinitionParserDelegate#parseMetaElements(Element ele, BeanMetadataAttributeAccessor attributeAccessor)
	public void parseMetaElements(Element ele, BeanMetadataAttributeAccessor attributeAccessor) {
		NodeList nl = ele.getChildNodes();
		for (int i = 0; i < nl.getLength(); i++) {
			Node node = nl.item(i);
			// 提取meta
			if (isCandidateElement(node) && nodeNameEquals(node, META_ELEMENT)) {
				Element metaElement = (Element) node;
				String key = metaElement.getAttribute(KEY_ATTRIBUTE);
				String value = metaElement.getAttribute(VALUE_ATTRIBUTE);
				// 使用 key、value 构造 BeanMetadataAttribute
				BeanMetadataAttribute attribute = new BeanMetadataAttribute(key, value);
				attribute.setSource(extractSource(metaElement));
				// 记录信息
				attributeAccessor.addMetadataAttribute(attribute);
			}
		}
	}
  • BeanDefinitionParserDelegate#parseLookupOverrideSubElements(Element beanEle, MethodOverrides overrides)
	public void parseLookupOverrideSubElements(Element beanEle, MethodOverrides overrides) {
		NodeList nl = beanEle.getChildNodes();
		for (int i = 0; i < nl.getLength(); i++) {
			Node node = nl.item(i);
			// 仅当在 Spring 默认 bean 的子元素且为 lookup-method 时有效
			if (isCandidateElement(node) && nodeNameEquals(node, LOOKUP_METHOD_ELEMENT)) {
				Element ele = (Element) node;
				String methodName = ele.getAttribute(NAME_ATTRIBUTE);
				String beanRef = ele.getAttribute(BEAN_ELEMENT);
				LookupOverride override = new LookupOverride(methodName, beanRef);
				override.setSource(extractSource(ele));
				overrides.addOverride(override);
			}
		}
	}
  • BeanDefinitionParserDelegate#parseReplacedMethodSubElements(Element beanEle, MethodOverrides overrides)
	public void parseReplacedMethodSubElements(Element beanEle, MethodOverrides overrides) {
		NodeList nl = beanEle.getChildNodes();
		for (int i = 0; i < nl.getLength(); i++) {
			Node node = nl.item(i);
			// 仅当在 Spring 默认 bean 的子元素且为 replaced-method 时有效
			if (isCandidateElement(node) && nodeNameEquals(node, REPLACED_METHOD_ELEMENT)) {
				Element replacedMethodEle = (Element) node;
				// 提取要替换的旧的方法
				String name = replacedMethodEle.getAttribute(NAME_ATTRIBUTE);

				// 提取对应的新的替换方法
				String callback = replacedMethodEle.getAttribute(REPLACER_ATTRIBUTE);
				ReplaceOverride replaceOverride = new ReplaceOverride(name, callback);

				// Look for arg-type match elements.
				/*
				 *  取出 arg-type 元素节点:
				 *      元素 replaced-method 可以使用其子元素 arg-type 来指定参数类型(字符串,例如String),如果没有
				 *  指定任何 arg-type 元素,则表示该方法无参。例如:
				 *  <replaced-method name="getAFFruit" replacer="methodReplacer">
				 *  	<arg-type match="java.lang.String"></arg-type>
				 *  </replaced-method>
				 */
				List<Element> argTypeEles = DomUtils.getChildElementsByTagName(replacedMethodEle, ARG_TYPE_ELEMENT);
				for (Element argTypeEle : argTypeEles) {
					// 记录参数
					String match = argTypeEle.getAttribute(ARG_TYPE_MATCH_ATTRIBUTE);
					// <arg-type>标签若有match属性值,则直接取值;否则查看 <arg-type>String</arg-type> 之间是否有值,有则取出
					match = (StringUtils.hasText(match) ? match : DomUtils.getTextValue(argTypeEle));
					if (StringUtils.hasText(match)) {
						// 增加参数类型
						replaceOverride.addTypeIdentifier(match);
					}
				}
				replaceOverride.setSource(extractSource(replacedMethodEle));
				overrides.addOverride(replaceOverride);
			}
		}
	}
  • BeanDefinitionParserDelegate#parseConstructorArgElements(Element beanEle, BeanDefinition bd)
	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);
			}
		}
	}
  • BeanDefinitionParserDelegate#parseConstructorArgElement(Element ele, BeanDefinition bd)

首先提取 constructor-arg 上必要的属性(index、type、name):

  • 如果配置中指定了 index 属性,name操作步骤如下:
  • 解析 constructor-arg 的子元素
  • 使用 ConstructorArgumentValues.ValueHolder 类型类封装解析出来的元素
  • 将 type、name 和 index 属性一并封装在 ConstructorArgumentValues.ValueHolder 类型中并添加至当前 BeanDefinitionConstructorArgumentValuesIndexedArgumentValue 属性中
  • 若没有指定 index 属性,name操作步骤如下:
  • 解析 constructor-arg 的子元素
  • 使用 ConstructorArgumentValues.ValueHolder 类型类封装解析出来的元素
  • 将 type、name 和 index 属性一并封装在 ConstructorArgumentValues.ValueHolder 类型中并添加至当前 BeanDefinitionConstructorArgumentValuesGenericArgumentValue 属性中
	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);
		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));
						// 解析 constructor-arg 对应的子元素
						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 {
			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();
			}
		}
	}
  • BeanDefinitionParserDelegate#parseConstructorArgElement(Element ele, BeanDefinition bd)

解析过程如下:

  1. 略过 description 或者 meta
  2. 提取 constructor-arg 上的 ref 和 value 属性,以便于根据规则验证正确性,其规则为在 constructor-arg 上不存在以下情况:
  • 同时既有 ref 属性又有 value 属性
  • 存在 ref 属性或者 value 属性且又有子元素
  1. ref 属性的处理,使用 RuntimeBeanReference 封装对应的 ref 名称,如:<constructor-arg ref="a">
  2. value 属性的处理,使用 TypedStringValue 封装对应的 value 名称,如:<constructor-arg value="a">
  3. 子元素的处理,如:
		<constructor-arg1>
			<map key-type="" value-type="" merge="">
				<entry key="key" value="value"></entry>
			</map>
		</constructor-arg>
	/**
	 * @param propertyName
	 *     为 null:解析 constructor-arg 子元素
	 *     不为null:解析 constructor-arg 属性
	 * Get the value of a property element. May be a list etc.
	 * Also used for constructor arguments, "propertyName" being null in this case.
	 */
	@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 等(这些属性互斥)
		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);
		/*
		 * 在 constructor-arg 上不存在:
		 *     1.同时既有 ref 属性又有 value 属性
		 *     2.存在 ref 属性或者 value 属性且又有子元素
		 */
		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) {
			// ref 属性的处理,使用 RuntimeBeanReference 封装对应的 ref 名称
			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) {
			// value 属性的处理,使用 TypedStringValue 封装对应的 value 名称
			TypedStringValue valueHolder = new TypedStringValue(ele.getAttribute(VALUE_ATTRIBUTE));
			valueHolder.setSource(extractSource(ele));
			return valueHolder;
		}
		else if (subElement != null) {
			// 处理 <constructor-arg> 子元素
			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;
		}
	}
  • BeanDefinitionParserDelegate#parsePropertySubElement(Element ele, @Nullable BeanDefinition bd)
	@Nullable
	public Object parsePropertySubElement(Element ele, @Nullable BeanDefinition bd) {
		return parsePropertySubElement(ele, bd, null);
	}
  • BeanDefinitionParserDelegate#parsePropertySubElement(Element ele, @Nullable BeanDefinition bd, @Nullable String defaultValueType)
	/**
	 * @param ele subelement of property element; we don't know which yet 对于解析 <constructor-arg> 的子元素而言,就是<ref>、<value>等
	 */
	@Nullable
	public Object parsePropertySubElement(Element ele, @Nullable BeanDefinition bd, @Nullable 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)) {
				// 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;
		}
		// 对 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)) {
			// It's a distinguished null value. Let's wrap it in a TypedStringValue
			// object in order to preserve the source location.
			TypedStringValue nullHolder = new TypedStringValue(null);
			nullHolder.setSource(extractSource(ele));
			return nullHolder;
		}
		// 对 array 子元素的解析
		else if (nodeNameEquals(ele, ARRAY_ELEMENT)) {
			return parseArrayElement(ele, bd);
		}
		// 对 list 子元素的解析
		else if (nodeNameEquals(ele, LIST_ELEMENT)) {
			return parseListElement(ele, bd);
		}
		// 对 set 子元素的解析
		else if (nodeNameEquals(ele, SET_ELEMENT)) {
			return parseSetElement(ele, bd);
		}
		// 对 map 子元素的解析
		else if (nodeNameEquals(ele, MAP_ELEMENT)) {
			return parseMapElement(ele, bd);
		}
		// 对 props 子元素的解析
		else if (nodeNameEquals(ele, PROPS_ELEMENT)) {
			return parsePropsElement(ele);
		}
		else {
			error("Unknown property sub-element: [" + ele.getNodeName() + "]", ele);
			return null;
		}
	}
  • BeanDefinitionParserDelegate#parsePropertyElements(Element beanEle, BeanDefinition bd)
	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);
			}
		}
	}
  • BeanDefinitionParserDelegate#parsePropertyElement(Element ele, BeanDefinition 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;
			}
			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();
		}
	}
  • BeanDefinitionParserDelegate#parseQualifierElements(Element beanEle, AbstractBeanDefinition bd)
	public void parseQualifierElements(Element beanEle, AbstractBeanDefinition bd) {
		NodeList nl = beanEle.getChildNodes();
		for (int i = 0; i < nl.getLength(); i++) {
			Node node = nl.item(i);
			if (isCandidateElement(node) && nodeNameEquals(node, QUALIFIER_ELEMENT)) {
				parseQualifierElement((Element) node, bd);
			}
		}
	}
  • BeanDefinitionParserDelegate#parseQualifierElement(Element beanEle, AbstractBeanDefinition bd)
	public void parseQualifierElement(Element ele, AbstractBeanDefinition bd) {
		String typeName = ele.getAttribute(TYPE_ATTRIBUTE);
		if (!StringUtils.hasLength(typeName)) {
			error("Tag 'qualifier' must have a 'type' attribute", ele);
			return;
		}
		this.parseState.push(new QualifierEntry(typeName));
		try {
			AutowireCandidateQualifier qualifier = new AutowireCandidateQualifier(typeName);
			qualifier.setSource(extractSource(ele));
			String value = ele.getAttribute(VALUE_ATTRIBUTE);
			if (StringUtils.hasLength(value)) {
				qualifier.setAttribute(AutowireCandidateQualifier.VALUE_KEY, value);
			}
			NodeList nl = ele.getChildNodes();
			for (int i = 0; i < nl.getLength(); i++) {
				Node node = nl.item(i);
				if (isCandidateElement(node) && nodeNameEquals(node, QUALIFIER_ATTRIBUTE_ELEMENT)) {
					Element attributeEle = (Element) node;
					String attributeName = attributeEle.getAttribute(KEY_ATTRIBUTE);
					String attributeValue = attributeEle.getAttribute(VALUE_ATTRIBUTE);
					if (StringUtils.hasLength(attributeName) && StringUtils.hasLength(attributeValue)) {
						BeanMetadataAttribute attribute = new BeanMetadataAttribute(attributeName, attributeValue);
						attribute.setSource(extractSource(attributeEle));
						qualifier.addMetadataAttribute(attribute);
					}
					else {
						error("Qualifier 'attribute' tag must have a 'name' and 'value'", attributeEle);
						return;
					}
				}
			}
			bd.addQualifier(qualifier);
		}
		finally {
			this.parseState.pop();
		}
	}
  • BeanDefinitionParserDelegate#decorateBeanDefinitionIfRequired(Element ele, BeanDefinitionHolder originalDef)
	public BeanDefinitionHolder decorateBeanDefinitionIfRequired(Element ele, BeanDefinitionHolder originalDef) {
		return decorateBeanDefinitionIfRequired(ele, originalDef, null);
	}
  • BeanDefinitionParserDelegate#decorateBeanDefinitionIfRequired(Element ele, BeanDefinitionHolder originalDef, @Nullable BeanDefinition containingBd)
	/**
	 * 第三个参数 containingBd 的作用:
	 *     这个参数是父类 bean,当对某个嵌套配置进行分析时,这里需要传递父类 beanDefinition。传递这个参数的目的是为了
	 * 使用父类的 scope 属性,以备子类若没有设置 scope 时默认使用父类的属性。
	 *
	 * 这个方法的作用:
	 *     在该方法中,对于程序默认的标签的处理其实是直接略过的,因为默认的标签到这里已经被处理完了,这里只对自定义的标
	 * 签或者说对 bean 的自定义属性感兴趣。在方法中实现了寻找自定义标签并根据自定义标签寻找命名空间处理器,并进行进一步
	 * 解析。
	 */
	public BeanDefinitionHolder decorateBeanDefinitionIfRequired(
			Element ele, BeanDefinitionHolder originalDef, @Nullable BeanDefinition containingBd) {

		BeanDefinitionHolder finalDefinition = originalDef;

		// 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;
	}
  • BeanDefinitionParserDelegate#decorateIfRequired(Node node, BeanDefinitionHolder originalDef, @Nullable BeanDefinition containingBd)
	/**
	 * 方法作用:
	 *     首先获取属性或者元素的命名空间,以此来判断该元素或者属性是否是用于自定义标签的解析条件,找出自定义类型
	 * 所对应的的 NamespaceHandler 并进行进一步解析。
	 */
	public BeanDefinitionHolder decorateIfRequired(
			Node node, BeanDefinitionHolder originalDef, @Nullable BeanDefinition containingBd) {
		// 获取自定义标签的命名空间
		String namespaceUri = getNamespaceURI(node);
		if (namespaceUri != null && !isDefaultNamespace(namespaceUri)) {
			// 根据命名空间找到对应的处理器
			NamespaceHandler handler = this.readerContext.getNamespaceHandlerResolver().resolve(namespaceUri);
			if (handler != null) {
				// 进行修饰
				BeanDefinitionHolder decorated =
						handler.decorate(node, originalDef, new ParserContext(this.readerContext, this, containingBd));
				if (decorated != null) {
					return decorated;
				}
			}
			else if (namespaceUri.startsWith("http://www.springframework.org/schema/")) {
				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;
	}
  • BeanDefinitionReaderUtils#registerBeanDefinition(BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry)
	public static void registerBeanDefinition(
			BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry)
			throws BeanDefinitionStoreException {

		// Register bean definition under primary name.
		// 使用 beanName 做唯一标识注册
		String beanName = definitionHolder.getBeanName();
		registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());

		// Register aliases for bean name, if any.
		// 注册所有别名
		String[] aliases = definitionHolder.getAliases();
		if (aliases != null) {
			for (String alias : aliases) {
				registry.registerAlias(beanName, alias);
			}
		}
	}
  • GenericApplicationContext#registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
	@Override
	public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
			throws BeanDefinitionStoreException {

		this.beanFactory.registerBeanDefinition(beanName, beanDefinition);
	}
  • DefaultListableBeanFactory#registerBeanDefinition(String beanName, BeanDefinition beanDefinition)

处理过程如下:
1.对 AbstractBeanDefinition 的校验。这里的校验不同于之前的 XML 文件校验,主要是对于 AbstractBeanDefinition 属性中的 methodOverrides 校验,校验 methodOverrides 是否与工厂方法并存或者 methodOverrides 对应的方法根本不存在。
2.对 beanName 已经注册的情况的处理。若设置了不容许 bean 的覆盖,则需要抛出异常,否则直接覆盖。
3.加入 map 缓存。
4.清除解析之前留下的对应 beanName 的缓存。

	@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) {
			try {
				/*
				 * 注册前的最后一次校验,这里的校验不同于之前的 XML 文件校验,
				 * 主要是对于 AbstractBeanDefinition 属性中的 methodOverrides 校验,
				 * 校验 methodOverrides 是否与工厂方法并存或者 methodOverrides 对应的方法根本不存在
				 */
				((AbstractBeanDefinition) beanDefinition).validate();
			}
			catch (BeanDefinitionValidationException ex) {
				throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,
						"Validation of bean definition failed", ex);
			}
		}

		BeanDefinition existingDefinition = this.beanDefinitionMap.get(beanName);
		// 处理已经注册的 beanName
		if (existingDefinition != null) {
			// 若对应的 BeanName 已经注册且在配置中配置了 bean 不容许被覆盖,则抛出异常
			if (!isAllowBeanDefinitionOverriding()) {
				throw new BeanDefinitionOverrideException(beanName, beanDefinition, existingDefinition);
			}
			else if (existingDefinition.getRole() < beanDefinition.getRole()) {
				// e.g. was ROLE_APPLICATION, now overriding with ROLE_SUPPORT or ROLE_INFRASTRUCTURE
				if (logger.isInfoEnabled()) {
					logger.info("Overriding user-defined bean definition for bean '" + beanName +
							"' with a framework-generated bean definition: replacing [" +
							existingDefinition + "] with [" + beanDefinition + "]");
				}
			}
			else if (!beanDefinition.equals(existingDefinition)) {
				if (logger.isDebugEnabled()) {
					logger.debug("Overriding bean definition for bean '" + beanName +
							"' with a different definition: replacing [" + existingDefinition +
							"] with [" + beanDefinition + "]");
				}
			}
			else {
				if (logger.isTraceEnabled()) {
					logger.trace("Overriding bean definition for bean '" + beanName +
							"' with an equivalent definition: replacing [" + existingDefinition +
							"] with [" + beanDefinition + "]");
				}
			}
			this.beanDefinitionMap.put(beanName, beanDefinition);
		}
		else {
			// 判断 bean 创建是否已经开始
			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 {
				// Still in startup registration phase
				// 依然处理启动注册阶段
				this.beanDefinitionMap.put(beanName, beanDefinition);
				this.beanDefinitionNames.add(beanName);
				removeManualSingletonName(beanName);
			}
			this.frozenBeanDefinitionNames = null;
		}

		if (existingDefinition != null || containsSingleton(beanName)) {
			// 重置所有 beanName 对应的缓存
			resetBeanDefinition(beanName);
		}
	}
  • ReaderContext#fireComponentRegistered(ComponentDefinition componentDefinition)
	public void fireComponentRegistered(ComponentDefinition componentDefinition) {
		this.eventListener.componentRegistered(componentDefinition);
	}
发布了444 篇原创文章 · 获赞 113 · 访问量 40万+

猜你喜欢

转载自blog.csdn.net/panchang199266/article/details/100822287