疑问 1:
@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) {
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 + "]");
}
}
this.beanDefinitionMap.put(beanName, beanDefinition);
}
else {
if (hasBeanCreationStarted()) {
// Cannot modify startup-time collection elements anymore (for stable iteration)
synchronized (this.beanDefinitionMap) {
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
this.beanDefinitionMap.put(beanName, beanDefinition);
this.beanDefinitionNames.add(beanName);
removeManualSingletonName(beanName);
}
this.frozenBeanDefinitionNames = null;
}
if (existingDefinition != null || containsSingleton(beanName)) {
resetBeanDefinition(beanName);
}
else if (isConfigurationFrozen()) {
clearByTypeCache();
}
}
其中这一段代码
if (hasBeanCreationStarted()) {
// Cannot modify startup-time collection elements anymore (for stable iteration)
synchronized (this.beanDefinitionMap) {
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
else {
// Still in startup registration phase
this.beanDefinitionMap.put(beanName, beanDefinition);
this.beanDefinitionNames.add(beanName);
removeManualSingletonName(beanName);
}
希望大家能给解答一下,万分感谢 !
1
shanghai1943 2023-08-30 10:50:10 +08:00 2
claude ai 的回复
hasBeanCreationStarted() 方法是用来判断 bean 定义注册是否处于启动阶段。 在 Spring 容器启动时,会有一个 bean 定义注册的过程,这个过程称为启动阶段。启动阶段结束后,会调用 finishBeanFactoryInitialization() 方法,设置启动阶段完成的标记。 之所以需要判断启动阶段,是因为在启动阶段和非启动阶段,bean 定义的注册逻辑有略微不同: 1. 启动阶段:可以直接修改 beanDefinitionMap 和 beanDefinitionNames 2. 非启动阶段:需要同步处理,避免多线程并发访问这些容器内存状态 else 分支就是处理非启动阶段的逻辑。当容器已经完成了启动,这个时候再注册 bean 定义,就需要加锁处理: 1. 同步包装 beanDefinitionMap 的修改 2. 创建 beanDefinitionNames 的拷贝进行修改 3. 删除 manualSingletonNames 里的对应名称 之所以这么设计,是因为启动阶段内存状态的变更频繁,如果都加锁处理会非常低效。所以启动阶段只 simply 修改状态,结束后再对状态变更加锁。 而 hasBeanCreationStarted()就是判断当前是否还在启动阶段,从而决定走哪种 bean 定义注册逻辑。 所以这个判断对提高整个容器的并发性能很重要。 |
2
liuyunlong OP 清晰明了,万分感谢
|