Spring源码解析-BeanName生成方法

1、环境要求

  • Spring V4.0.8.RELEASE

  • 基于XML配置方式加载Bean

2、BeanName生成方法

spring优先将标签的id属性值作为beanName,没有配置id则将name属性值第一个元素作为beanName。下面代码片段摘自BeanDefinitionParserDelegate的parseBeanDefinitionElement方法

String id = ele.getAttribute(ID_ATTRIBUTE);
		String nameAttr = ele.getAttribute(NAME_ATTRIBUTE);

		List<String> aliases = new ArrayList<String>();
		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()) {
			//如果没有配置id,则将name第一个元素作为id
			beanName = aliases.remove(0);
			if (logger.isDebugEnabled()) {
				logger.debug("No XML 'id' specified - using '" + beanName +
						"' as bean name and " + aliases + " as aliases");
			}
		}

如果没有配置name则使用BeanName生成器生成,spring提供了个默认生成器DefaultBeanNameGenerator,它最终还是要委托给类BeanDefinitionReaderUtils去实现这个刚功能,默认实现方法:

public static String generateBeanName(
			BeanDefinition definition, BeanDefinitionRegistry registry, boolean isInnerBean)
			throws BeanDefinitionStoreException {
		//读取className
		String generatedBeanName = definition.getBeanClassName();
		if (generatedBeanName == null) {
			if (definition.getParentName() != null) {
				//definition.getParentName() 就是<bean>标签中配置的parent属性值
				generatedBeanName = definition.getParentName() + "$child";
			}
			else if (definition.getFactoryBeanName() != null) {
				//definition.getFactoryBeanName() 就是<bean>标签中配置的factory-bean属性值
				generatedBeanName = definition.getFactoryBeanName() + "$created";
			}
		}
		if (!StringUtils.hasText(generatedBeanName)) {
			throw new BeanDefinitionStoreException("Unnamed bean definition specifies neither " +
					"'class' nor 'parent' nor 'factory-bean' - can't generate bean name");
		}

		String id = generatedBeanName;
		//判断是否是子标签Bean,按不同方式生成唯一beanName
		if (isInnerBean) {
			// Inner bean: generate identity hashcode suffix.
			id = generatedBeanName + GENERATED_BEAN_NAME_SEPARATOR + ObjectUtils.getIdentityHexString(definition);
		}
		else {
			// Top-level bean: use plain class name.
			// Increase counter until the id is unique.
			int counter = -1;
			while (counter == -1 || registry.containsBeanDefinition(id)) {
				counter++;
				id = generatedBeanName + GENERATED_BEAN_NAME_SEPARATOR + counter;
			}
		}
		return id;
	}

默认生成的beanName要么是以16进制字符结尾要么以#+数字字符结尾。

如果想自定义生成器可以继承XmlWebApplicationContext 然后重写它的initBeanDefinitionReader方法,在方法体内调用XmlBeanDefinitionReader的setBeanNameGenerator方法重新赋值

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值