spring标签中的id和name区别,BeanDefinitionParserDelegate类

我们将从官方说明和spring的源码中找到关于id和name的相关规则:

官方文档:

Every bean has one or more identifiers.
These identifiers must be unique within the container that hosts the bean.
A bean usually has only one identifier, but if it requires more than one, the extra ones can be considered aliases.
In XML-based configuration metadata, you use the id and/or name attributes to specify the bean identifier(s).
The id attribute allows you to specify exactly one id.
If you want to introduce other aliases to the bean, you can also specify them in the name attribute, separated by a comma (,), semicolon (;), or white space.

也就是说:
id和name本质上其实是相同的,都可以唯一地标识一个bean。区别是id只能定义一个值,name可以定义多个值(separated by a comma (,), semicolon (😉, or white space)。但是仍有一定的唯一标识符规则:

  1. 配置一个bean的时候,可以不设置id,也可以不设置name,spring默认会使用类的全限定名作为bean的标识符。
  2. 如果设置id属性,那么id就是bean的唯一标识符,在spring容器中必需唯一。
  3. 如果仅设置name属性,那么name就是bean的唯一标识符,必需在容器中唯一。
  4. 如果同时设置id和name,那么id是唯一标识符,name是别名。如果id和name的值相同,那么spring容器会自动检测并消除冲突:让这个bean只有标识符,而没有别名。
  5. name属性设置多个值且不设置id属性,那么第一个被用作标识符,其他的被视为别名。如果设置了id,那么name的所有值都是别名。
  6. 不管是标识符,还是别名,在容器中必需唯一。因为标识符和别名,都是可以用来获取bean的,如果不唯一,显然不知道获取的到底是哪儿一个bean。

以上推论我们也可以在spring中源码找到依据:
SpringFrameWork源码:
package org.springframework.beans.factory.xml.BeanDefinitionParserDelegate源码:

/**
	 * Parses the supplied {@code <bean>} element. May return {@code null}
	 * if there were errors during parse. Errors are reported to the
	 * {@link org.springframework.beans.factory.parsing.ProblemReporter}.
	 */
	@Nullable
	public BeanDefinitionHolder parseBeanDefinitionElement(Element ele, @Nullable BeanDefinition containingBean) {
		String id = ele.getAttribute(ID_ATTRIBUTE);
		String nameAttr = ele.getAttribute(NAME_ATTRIBUTE);

		// 解析name并且放入 aliases 中
		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;
		// beanName是无效 且 aliases 非空
		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");
			}
		}
		//从方法名字上都可以看出来,此方法是为了检查beanName是是唯一的
		if (containingBean == null) {
			checkNameUniqueness(beanName, aliases, ele);
		}

		//将解析到的信息 封装到 AbstractBeanDefinition 中
		AbstractBeanDefinition beanDefinition = parseBeanDefinitionElement(ele, beanName, containingBean);
		//如果上述规则不匹配就默认为类的全限定类名为唯一标识
		if (beanDefinition != null) {
			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.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);
			return new BeanDefinitionHolder(beanDefinition, beanName, aliasesArray);
		}

		return null;
	}

以上

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

杰夫·王盖茨

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值