finishbeanfactoryinitialization 是 spring 容器启动时触发非懒加载单例 bean 实例化的关键方法,通过 preinstantiatesingletons 遍历注册的 beandefinition,调用 dogetbean 启动生命周期;其核心依托三级缓存机制(singletonobjects、earlysingletonobjects、singletonfactories)协同完成实例化、依赖注入、初始化及循环依赖解决;docreatebean 分三步执行:实例化、提前暴露 objectfactory 至三级缓存、属性填充与初始化;factorybean 和 smartinitializingsingleton 有特殊处理逻辑。

在 Spring 容器启动过程中,finishBeanFactoryInitialization 是真正触发所有非懒加载单例 Bean 实例化的关键方法。它不负责“定义”或“注册”Bean,而是驱动整个单例 Bean 的创建、依赖注入、初始化(包括 @PostConstruct、InitializingBean、自定义 init-method)和早期暴露(解决循环依赖)流程。
核心入口:调用 beanFactory.preInstantiateSingletons()
该方法内部委托给 DefaultListableBeanFactory.preInstantiateSingletons(),这是单例实例化的总闸门:
- 遍历所有已注册的 BeanDefinition(排除抽象、懒加载、FactoryBean 类型的 Bean)
- 对每个非懒加载单例 Bean,调用
getBean(beanName)—— 这是整个 Bean 生命周期的起点 - 注意:
getBean是模板方法,实际走的是AbstractBeanFactory.doGetBean()
关键步骤:doGetBean 中的三级缓存与创建逻辑
单例实例化不是简单 new 一下,而是围绕三级缓存协同完成,尤其为解决循环依赖设计:
- 一级缓存(singletonObjects):存放完全初始化好的单例 Bean(成品)
- 二级缓存(earlySingletonObjects):存放提前暴露的、尚未完成属性注入的原始对象(半成品)
- 三级缓存(singletonFactories):存放 ObjectFactory,用于按需创建早期引用(避免每次 getEarlyBeanReference 都重复创建)
- 当
doGetBean发现 Bean 不存在于一级缓存时,会:- 先检查三级缓存,若存在对应工厂,则通过
getObject()获取早期引用并放入二级缓存,同时从三级缓存移除 - 调用
createBean()(最终到doCreateBean())执行真实创建
- 先检查三级缓存,若存在对应工厂,则通过
真实创建:doCreateBean 的三步走
这个方法是单例 Bean “从无到有”的核心实现:
- 1. 实例化(instantiateBean):根据构造器、工厂方法或 Supplier 创建原始对象(此时无任何属性赋值)
- 2. 提前暴露(addSingletonFactory):若允许循环引用(默认 true),将 ObjectFactory 放入三级缓存,供其他 Bean 在注入阶段获取早期引用
-
3. 属性填充 & 初始化(populateBean + initializeBean):
-
populateBean:完成依赖注入(@Autowired、@Resource、setter、constructor) -
initializeBean:依次执行 Aware 接口回调 →@PostConstruct→InitializingBean.afterPropertiesSet()→ 自定义init-method
-
- 最后,将完全初始化好的 Bean 放入一级缓存,并清空二、三级缓存中对应条目
特殊处理:FactoryBean 和 SmartInitializingSingleton
并非所有单例都直接是业务 Bean:
- 若 Bean 是
FactoryBean类型,preInstantiateSingletons会额外调用其getObject(),并将返回对象作为最终单例(名字带&前缀的才是 FactoryBean 本身) - 实现了
SmartInitializingSingleton接口的 Bean,会在所有单例初始化完成后,统一回调其afterSingletonsInstantiated()方法(常用于容器启动后统一注册监听器等)
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











