在Spring中,提供了BeanNameGenerator来生成BeanName.
public interface BeanNameGenerator {
String generateBeanName(BeanDefinition var1, BeanDefinitionRegistry var2);
}
查看关系图,我们可以看到。
DefaultBeanNameGenerator
XML配置中,默认生成BeanName。
public class DefaultBeanNameGenerator implements BeanNameGenerator {
public static final DefaultBeanNameGenerator INSTANCE = new DefaultBeanNameGenerator();
public DefaultBeanNameGenerator() {
}
public String generateBeanName(BeanDefinition definition, BeanDefinitionRegistry registry) {
return BeanDefinitionReaderUtils.generateBeanName(definition, registry);
}
}
我们可以看到,DefaultBeanNameGenerator这个类内部,实际上是generateBeanName这个方法去通过 BeanDefinitionReaderUtils.generateBeanName(definition, registry);去生成BeanName的。
public static String generateBeanName(BeanDefinition definition, BeanDefinitionRegistry registry, boolean isInnerBean) throws BeanDefinitionStoreException {
//从xml文件中获取到BeanName
String generatedBeanName = definition.getBeanClassName();
if (generatedBeanName == null) {
//如果BeanName为null则去获取他的父类,通过父类名+$child组成BeanName
if (definition.getParentName() != null) {
generatedBeanName = definition.getParentName() + "$child";
} else if (definition.getFactoryBeanName() != null)//如果父类名也没有,则使用factoryBeanName尝试获取 {
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");
} else {
//否则,调用uniqueBeanName方法去生成BeanName.
return isInnerBean ? generatedBeanName + "#" + ObjectUtils.getIdentityHexString(definition) : uniqueBeanName(generatedBeanName, registry);
}
}
public static String uniqueBeanName(String beanName, BeanDefinitionRegistry registry) {
String id = beanName;
int counter = -1;
//将类的全路径和#拼在一起,并且判断id是否已被注册,如果注册,则下一个,生成一个新的id.
for(String prefix = beanName + "#"; counter == -1 || registry.containsBeanDefinition(id); id = prefix + counter) {
++counter;
}
return id;
}
AnnotationBeanNameGenerator
Java配置中,如果使用了@Component注解,则使用这个来生成BeanName.
我们可以看到,在使用Java配置的时候,一般只使用一个@Bean()注解,实际上,点进去查看,就会发现,@Bean()注解内部已经使用了@Component注解。
@Target({ElementType.METHOD, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Bean {}
Id和Name的处理原理
id和Name的属性处理也是在BeanDefinitionParserDelegate#parseBeanDefinitionElement这个方法中,获取id和name,
如果nameAttr有参数,则基于,空格等格式进行拆分,然后将拆出来的属性,作为bean的别名。
下面,if则进行判断,没有id属性,但是有name属性,则将拆出来的第一项,作为beanName.
String id = ele.getAttribute("id");
String nameAttr = ele.getAttribute("name");
List<String> aliases = new ArrayList();
if (StringUtils.hasLength(nameAttr)) {
String[] nameArr = StringUtils.tokenizeToStringArray(nameAttr, ",; ");
aliases.addAll(Arrays.asList(nameArr));
}
String beanName = id;
if (!StringUtils.hasText(id) && !aliases.isEmpty()) {
beanName = (String)aliases.remove(0);
if (this.logger.isTraceEnabled()) {
this.logger.trace("No XML 'id' specified - using '" + beanName + "' as bean name and " + aliases + " as aliases");
}
}
如果经过以上的处理,beanName还是空的,则进入到之前的循环,系统自动给定一个BeanName.