Серия исходных кодов Spring: загрузка BeanDefinition (ниже)

задняя часть Spring исходный код

существуетСерия исходных кодов Spring: загрузка BeanDefinition (включена)Процесс синтаксического анализа был в общих чертах описан в этой статье, и в этой статье будет описан процесс регистрации бина.

Регистрация bean-компонентов выполняется методом registerBeanDefinition в DefaultListableBeanFactory. Затем я рассмотрю конкретную логику метода registerBeanDefinition.

1. Оценка типа beanDefinition и проверка

Проверка здесь в основном предназначена для проверки того, что статические фабричные методы нельзя комбинировать с переопределением методов (статические фабричные методы должны создавать экземпляры);

if (beanDefinition instanceof AbstractBeanDefinition) {
try {
((AbstractBeanDefinition) beanDefinition).validate();
}
catch (BeanDefinitionValidationException ex) {
throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(),
beanName,"Validation of bean definition failed", ex);
}
}

2. Попробуйте получить старый бин из beanDefinitionMap

Здесь нужно сначала получить BeanDefinition из beanDefinitionMap в соответствии с beanName и передать результат в oldBeanDefinition.

BeanDefinition oldBeanDefinition;
oldBeanDefinition = this.beanDefinitionMap.get(beanName);

3. Beandefinition с именем beanName уже существует в beanDefinitionMap.

Если BeanDefinition с именем beanName уже существует в текущем beanDefinitionMap (т. е. проверьте, было ли зарегистрировано beanDefinition с тем же именем в контейнере Ioc). , если да, реализуйте следующие конкретные стратегии:

  • Если bean-компонент не может быть перезаписан, он будет выброшен напрямую и не может быть перерегистрирован, bean-компонент уже существует с такой информацией об исключении.
  • Используйте bean-компоненты, сгенерированные фреймворком, вместо пользовательских bean-компонентов.
  • Переопределить исходное Beandefinition
if (oldBeanDefinition != null) {
if (!isAllowBeanDefinitionOverriding()) {
//省略异常代码
}
else if (oldBeanDefinition.getRole() < beanDefinition.getRole()) {
//省略异常代码
}
else if (!beanDefinition.equals(oldBeanDefinition)) {
//提示覆盖log信息
}
else {
//提示覆盖log信息
}
//覆盖原有的Beandefinition
this.beanDefinitionMap.put(beanName, beanDefinition);
}

4. В beanDefinitionMap нет определения Beandefinition с именем beanName.

//检查bean的创建阶段是否已经开始,也就是说是否已经创建了
if (hasBeanCreationStarted()) {
//Cannot modify startup-time collection elements anymore (for stable iteration)
// 无法修改启动时间收集元素(用于稳定迭代)(译注)
//注册过程需要保证数据的一致性,所有需要加锁同步
synchronized (this.beanDefinitionMap) {
//注册到beanDefinitionMap中
this.beanDefinitionMap.put(beanName, beanDefinition);
//下面就是将当前beanName存放到beanDefinitionNames中
List<String> updatedDefinitions = new ArrayList<String>(
this.beanDefinitionNames.size() + 1);
updatedDefinitions.addAll(this.beanDefinitionNames);
updatedDefinitions.add(beanName);
this.beanDefinitionNames = updatedDefinitions;
//如果单例模式的bean名单中有该bean的name,那么移除掉它。
//也就是说着,将一个原本是单例模式的bean重新注册成一个普通的bean
if (this.manualSingletonNames.contains(beanName)) {
Set<String> updatedSingletons = new
LinkedHashSet<String>(this.manualSingletonNames);
updatedSingletons.remove(beanName);
this.manualSingletonNames = updatedSingletons;
}
}
}
// 仍处于启动阶段,bean还没有开始注册
else {
// Still in startup registration phase
this.beanDefinitionMap.put(beanName, beanDefinition);
this.beanDefinitionNames.add(beanName);
this.manualSingletonNames.remove(beanName);
}
this.frozenBeanDefinitionNames = null;

5. Выполните очистку кеша

  • 1: Если oldBeanDefinition существует, и здесь не выдается исключение, это означает, что BeanDefinition был перезаписан и кэш необходимо обновить.

  • 2: Если это объект bean-компонента одноэлементного режима, Set содержит beanName.Выполнение здесь указывает, что BeanDefinition изменился с bean-компонента singleton на обычный bean-компонент, поэтому кэш также необходимо обновить.

if (oldBeanDefinition != null || containsSingleton(beanName)) {
resetBeanDefinition(beanName);
}

Хорошо, давайте посмотрим на метод resetBeanDefinition:

这个方法的作用就是重置给定bean的所有bean定义缓存,包括从它派生的bean的缓存。

protected void resetBeanDefinition(String beanName) {
// 如果已经创建,则删除给定bean的合并bean定义。
clearMergedBeanDefinition(beanName);

// 如果有的话,从singleton 高速缓存中删除相应的bean。
//但是这也不是必须的,而只是为了覆盖上下文的默认bean
//(就是从manualSingletonNames中移除)
destroySingleton(beanName);
//递归的方式来 重置具有给定bean作为父项的所有bean定义。
for (String bdName : this.beanDefinitionNames) {
if (!beanName.equals(bdName)) {
BeanDefinition bd = this.beanDefinitionMap.get(bdName);
if (beanName.equals(bd.getParentName())) {
resetBeanDefinition(bdName);
}
}
}
}

Регистрация bean-компонентов здесь Следующая статья посвящена контейнеру DefaultListableBeanFactory.