Spring 源码解析:finishBeanFactoryInitialization方法深度剖析

93 阅读3分钟

Spring 源码解析:finishBeanFactoryInitialization方法深度剖析

在Spring框架中,finishBeanFactoryInitialization方法是容器初始化的核心步骤之一,负责完成非延迟加载的单例Bean的实例化和初始化。本文将深入分析该方法的实现逻辑、关键设计思想,并总结相关面试考点。


一、方法定位与作用

方法路径
org.springframework.context.support.AbstractApplicationContext#finishBeanFactoryInitialization

调用时机
在Spring容器的refresh()流程中,finishBeanFactoryInitialization是第9步(共12步)被调用,标志着配置解析完成,开始实例化所有非延迟初始化的单例Bean。

核心作用

  1. 冻结配置:确保所有Bean定义已加载且不再修改。
  2. 预实例化单例Bean:触发所有非延迟加载的单例Bean的实例化、依赖注入及初始化。

二、源码逐层解析

1. 冻结BeanFactory配置

beanFactory.freezeConfiguration(); // 禁止修改Bean定义

2. 初始化单例Bean

核心逻辑通过DefaultListableBeanFactory#preInstantiateSingletons实现:

public void preInstantiateSingletons() throws BeansException {
    List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);

    for (String beanName : beanNames) {
        RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
        if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
            if (isFactoryBean(beanName)) { // 处理FactoryBean
                // ... 实例化FactoryBean逻辑
            } else {
                getBean(beanName); // 触发普通Bean的实例化
            }
        }
    }

    // 触发SmartInitializingSingleton回调
    for (String beanName : beanNames) {
        Object singletonInstance = getSingleton(beanName);
        if (singletonInstance instanceof SmartInitializingSingleton) {
            ((SmartInitializingSingleton) singletonInstance).afterSingletonsInstantiated();
        }
    }
}

3. Bean实例化流程

调用getBean()会触发以下关键步骤:

  1. 创建Bean实例:通过反射或工厂方法实例化对象。
  2. 属性填充:通过populateBean注入依赖(包括自动装配)。
  3. 初始化Bean:执行BeanPostProcessorInitializingBean接口及init-method
  4. 注册销毁逻辑:注册DisposableBeandestroy-method

三、关键设计思想

1. 模板方法模式

  • 冻结配置:确保后续流程不可修改Bean定义,保证线程安全。
  • 延迟初始化控制:通过isLazyInit区分Bean的加载时机。

2. 扩展点设计

  • BeanPostProcessor:在Bean初始化前后插入自定义逻辑(如AOP代理)。
  • SmartInitializingSingleton:所有单例Bean初始化完成后触发扩展逻辑。

3. 循环依赖处理

  • 三级缓存:通过singletonFactoriesearlySingletonObjectssingletonObjects解决循环依赖。

四、面试高频考点与答案

考点1:finishBeanFactoryInitialization的作用?

答案
该方法负责实例化所有非延迟加载的单例Bean,确保它们完成依赖注入和初始化。它是Spring容器启动的关键阶段,标志着从配置解析转向Bean实例化。


考点2:Bean的初始化流程包括哪些步骤?

答案

  1. 实例化Bean对象(通过构造器或工厂方法)。
  2. 属性注入(@Autowired或XML配置)。
  3. 调用BeanPostProcessor.postProcessBeforeInitialization
  4. 执行InitializingBean.afterPropertiesSet或自定义init-method
  5. 调用BeanPostProcessor.postProcessAfterInitialization

考点3:Spring如何解决循环依赖?

答案
通过三级缓存机制:

  1. singletonFactories:存储未完成初始化的Bean工厂对象(用于提前暴露引用)。
  2. earlySingletonObjects:存储早期未完成属性注入的Bean(解决循环依赖)。
  3. singletonObjects:存储完全初始化后的Bean。
    仅支持单例作用域且通过Setter注入的循环依赖。

考点4:SmartInitializingSingleton接口的作用?

答案
该接口的afterSingletonsInstantiated方法在所有单例Bean初始化完成后调用,适合执行依赖检查或启动后台任务。例如,Spring Boot的CommandLineRunner实现即基于此扩展点。


考点5:为什么需要冻结BeanFactory配置?

答案
冻结配置(freezeConfiguration)是为了防止后续流程中修改Bean定义,避免并发问题。此时所有Bean定义已解析完毕,确保实例化阶段的线程安全性。


五、总结

finishBeanFactoryInitialization是Spring容器启动的“临门一脚”,其设计体现了以下思想:

  1. 分层职责:将配置解析与实例化分离。
  2. 扩展性:通过BeanPostProcessor等接口支持功能扩展。
  3. 性能优化:预实例化单例Bean以提高运行时效率。

理解此方法对掌握Spring容器生命周期和解决复杂依赖问题至关重要。