SpringBoot 基础概念:注册BeanDefinition
1. 前言
问题:为什么需要注册BeanDefinition?
为了后续实例化。Spring架构是将Bean的定义信息注册流程和Bean的实例化过程分开的。
BeanDefinition就是对Bean的定义的信息,包含了class等信息。
2. BeanDefinitionReaderUtils#registerBeanDefinition
/**
* Register the given bean definition with the given bean factory.
* @param definitionHolder the bean definition including name and aliases
* @param registry the bean factory to register with
* @throws BeanDefinitionStoreException if registration failed
*/
public static void registerBeanDefinition(
BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry)
throws BeanDefinitionStoreException {
// Register bean definition under primary name.
String beanName = definitionHolder.getBeanName();
registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());
// Register aliases for bean name, if any.
String[] aliases = definitionHolder.getAliases();
if (aliases != null) {
for (String alias : aliases) {
registry.registerAlias(beanName, alias);
}
}
}
- 该方法是注册BeanDefinition的工具方法。
- 参数:
definitionHolder:是对BeanDefinition的封装,里面有beanName和aliases(bean的别名)。
BeanDefinitiion:Bean的一些定义信息,包含class信息。
registry:可以理解为DefaultListableBeanFactory。 - 将BeanDefinition注册到DefaultListableBeanFactory。将别名与beanName进行绑定,方便通过别名获取bean,别名与bean的名称是不能相互依赖的。
3. DefaultListableBeanFactory#registerBeanDefinition
@Override
public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
throws BeanDefinitionStoreException {
Assert.hasText(beanName, "Bean name must not be empty");
Assert.notNull(beanDefinition, "BeanDefinition must not be null");
if (beanDefinition instanceof AbstractBeanDefinition) {
try {
((AbstractBeanDefinition) beanDefinition).validate();
}
catch (BeanDefinitionValidationException ex) {
throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,
"Validation of bean definition failed", ex);
}
}
BeanDefinition existingDefinition = this.beanDefinitionMap.get(beanName);
if (existingDefinition != null) {
//如果已经注册了BeanDefinition,那么就判断是否循序覆盖,不允许覆盖则抛出异常
if (!isAllowBeanDefinitionOverriding()) {
throw new BeanDefinitionOverrideException(beanName, beanDefinition, existingDefinition);
}
else if (existingDefinition.getRole() < beanDefinition.getRole()) {
// e.g. was ROLE_APPLICATION, now overriding with ROLE_SUPPORT or ROLE_INFRASTRUCTURE
if (logger.isInfoEnabled()) {
logger.info("Overriding user-defined bean definition for bean '" + beanName +
"' with a framework-generated bean definition: replacing [" +
existingDefinition + "] with [" + beanDefinition + "]");
}
}
else if (!beanDefinition.equals(existingDefinition)) {
if (logger.isDebugEnabled()) {
logger.debug("Overriding bean definition for bean '" + beanName +
"' with a different definition: replacing [" + existingDefinition +
"] with [" + beanDefinition + "]");
}
}
else {
if (logger.isTraceEnabled()) {
logger.trace("Overriding bean definition for bean '" + beanName +
"' with an equivalent definition: replacing [" + existingDefinition +
"] with [" + beanDefinition + "]");
}
}
//注册BeanDefinition
this.beanDefinitionMap.put(beanName, beanDefinition);
}
else {
//没有注册相同的BeanDefinition
if (hasBeanCreationStarted()) {
//已经开始了实例化Bean
// Cannot modify startup-time collection elements anymore (for stable iteration)
synchronized (this.beanDefinitionMap) {
//使用了copyOnWrite原理,读写分离地去注册BeanDefinition
this.beanDefinitionMap.put(beanName, beanDefinition);
List<String> updatedDefinitions = new ArrayList<>(this.beanDefinitionNames.size() + 1);
updatedDefinitions.addAll(this.beanDefinitionNames);
updatedDefinitions.add(beanName);
this.beanDefinitionNames = updatedDefinitions;
//移除了手动注册的单例名称
removeManualSingletonName(beanName);
}
}
else {
// Still in startup registration phase
//如果依然在注册BeanDefinition的阶段,那么就直接去注册BeanDefinition
this.beanDefinitionMap.put(beanName, beanDefinition);
this.beanDefinitionNames.add(beanName);
//移除了手动注册的单例名称
removeManualSingletonName(beanName);
}
this.frozenBeanDefinitionNames = null;
}
//如果单例池中已经注册了相同的实例,那么就重置BeanDefinition
if (existingDefinition != null || containsSingleton(beanName)) {
resetBeanDefinition(beanName);
}
}
- 如果已经注册了BeanDefinition,那么就判断是否循序覆盖,不允许覆盖则抛出异常。是否允许覆盖是在spring.main.allow-bean-definition-overriding配置,在SpringBoot启动流程中有讲解。
SpringBoot 源码解析2:启动流程 - 如果已经该是实例化Bean的流程,那么就使用copyOnWrite原理注册BeanDefinition和beanName。因为Bean的实例化流程可能是用户多线程去getBean的,就会引发线程安全问题。
- 如果没有开始实例化流程,那么就直接注册BeanDefinition和BeanName。
- 移除了手动注册的beanName,Spring原则是优先使用用户配置,再使用内部默认配置。
- 如果单例池中已经注册了相同的实例,那么就重置BeanDefinition,即删除单例池中的对象,重新注册BeanDefinition,后续重新去实例化。