无涯

无所谓无 无所谓有

Spring Bean 命名源码分析

前言

Spring在进行Bean注册的时候需要有一个唯一标识,这个标识也成为BeanName。在进行Bean注册时,这个id并不必填项,它可以由Spring自动生成。下面就来讨论其中一种生成策略。

BeanNameGenerator

org.springframework.beans.factory.support.BeanNameGenerator这个接口就是Spring Bean名称生成器。我们看下源码

1
2
3
4
5
6
7
8
9
10
11
12
13
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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
/**
* 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

真正的实现是这个工具类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
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,如果是非内部类,会做唯一性校验

1
2
3
4
5
6
7
8
9
10
11
12
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,然后去容器里面看是否被注册,如果被组成则序号加一

写得比较粗糙,有时间会详细写一下