title: Spring Bean 命名源码分析
date: 2021-01-19 23:05:22
tags: Spring-Framework
前言
Spring在进行Bean注册的时候需要有一个唯一标识,这个标识也成为BeanName
。在进行Bean注册时,这个id
并不必填项,它可以由Spring自动生成。下面就来讨论其中一种生成策略。
BeanNameGenerator
org.springframework.beans.factory.support.BeanNameGenerator
这个接口就是Spring Bean名称生成器。我们看下源码
public interface BeanNameGenerator {
/**
* Generate a bean name for the given bean definition.
* @param definition the bean definition to generate a name for
* @param registry the bean definition registry that the given definition
* is supposed to be registered with
* @return the generated bean name
*/
String generateBeanName(BeanDefinition definition, BeanDefinitionRegistry registry);
}
该接口只定义了一个方法用于获取BeanName,需要传入BeanDefinition
BeanDefinitionRegistry
这里简单说明下为什么需要这两个参数
-
BeanDefinition
用于获取该Bean的ClassName
-
BeanDefinitionRegistry
用于判断生成的BeanName
是否已注册,如果已注册会附加类似#0
这样的序列号
BeanNameGenerator 实现类
这个接口有两个实现 DefaultBeanNameGenerator
AnnotationBeanNameGenerator
这里我们暂时只讨论前者,这个名称生成器的默认实现
DefaultBeanNameGenerator
/**
* Default implementation of the {@link BeanNameGenerator} interface, delegating to
* {@link BeanDefinitionReaderUtils#generateBeanName(BeanDefinition, BeanDefinitionRegistry)}.
*
* @author Juergen Hoeller
* @since 2.0.3
*/
public class DefaultBeanNameGenerator implements BeanNameGenerator {
/**
* A convenient constant for a default {@code DefaultBeanNameGenerator} instance,
* as used for {@link AbstractBeanDefinitionReader} setup.
* @since 5.2
*/
public static final DefaultBeanNameGenerator INSTANCE = new DefaultBeanNameGenerator();
@Override
public String generateBeanName(BeanDefinition definition, BeanDefinitionRegistry registry) {
return BeanDefinitionReaderUtils.generateBeanName(definition, registry);
}
}
这个默认实现类,存在一个单例对象,看doc是5.2才加的,因为要兼容之前的版本,所以没有私有化构造器
该实现类,委托给BeanDefinitionReaderUtils
实现功能
BeanDefinitionReaderUtils
真正的实现是这个工具类
public static String generateBeanName(
BeanDefinition definition, BeanDefinitionRegistry registry, boolean isInnerBean)
throws BeanDefinitionStoreException {
String generatedBeanName = definition.getBeanClassName();
if (generatedBeanName == null) {
if (definition.getParentName() != null) {
generatedBeanName = definition.getParentName() + "$child";
}
else if (definition.getFactoryBeanName() != null) {
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;
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 with unique suffix if necessary.
return uniqueBeanName(generatedBeanName, registry);
}
return id;
}
这里可以看出id是直接取的Bean的ClassName,如果是非内部类,会做唯一性校验
public static String uniqueBeanName(String beanName, BeanDefinitionRegistry registry) {
String id = beanName;
int counter = -1;
// Increase counter until the id is unique.
while (counter == -1 || registry.containsBeanDefinition(id)) {
counter++;
id = beanName + GENERATED_BEAN_NAME_SEPARATOR + counter;
}
return id;
}
每个beanName都会被加上#0,然后去容器里面看是否被注册,如果被组成则序号加一
写得比较粗糙,有时间会详细写一下