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方法重新赋值