这些 BeanDefinition 到底是哪一行代码、在哪个时间点,真正变成「看得见摸得着」的 Bean 实例,并塞进 BeanFactory 的?
1. 结论
Bean 的创建(初始化)发生在
AbstractApplicationContext#refresh()
→
finishBeanFactoryInitialization(beanFactory)
→
beanFactory.preInstantiateSingletons()
→
AbstractBeanFactory#getBean(name)
→
doGetBean(...)
→
createBean(...)
→
实例化、填充、初始化、代理,最终放进 DefaultSingletonBeanRegistry 的一级缓存(singletonObjects)。
2. 全景时序图
scss
启动主类 main()
└─ SpringApplication.run()
└─ new AnnotationConfigApplicationContext()
└─ refresh() // AbstractApplicationContext
├─ 1. prepareRefresh()
├─ 2. obtainFreshBeanFactory() // 已有 BeanDefinition,但无实例
├─ 3. postProcessBeanFactory()
├─ 4. invokeBeanFactoryPostProcessors() // 解析 @ComponentScan、@Configuration
├─ 5. registerBeanPostProcessors() // 注册后置处理器
├─ 6. initMessageSource()
├─ 7. initApplicationEventMulticaster()
├─ 8. onRefresh()
├─ 9. finishBeanFactoryInitialization() // ← 今天的主角
│ └─ beanFactory.preInstantiateSingletons()
│ └─ getBean(beanName) // 首次触发创建
│ └─ doCreateBean()
│ ├─ createBeanInstance() // 反射 or CGLIB 构造
│ ├─ populateBean() // 依赖注入
│ └─ initializeBean() // Aware、@PostConstruct、init-method、AOP 代理
└─ 10. finishRefresh() // 事件发布,启动完成
3. 关键代码逐行定位
阶段 | 类 / 方法 | 行号(6.x 版本) | 说明 |
---|---|---|---|
入口 | AbstractApplicationContext#finishBeanFactoryInitialization |
913 行 | 显式转换 beanFactory → DefaultListableBeanFactory |
循环 | DefaultListableBeanFactory#preInstantiateSingletons |
928 行 | 遍历所有 非抽象、单例、非懒加载 的 BeanDefinition |
触发 | AbstractBeanFactory#getBean(beanName) |
211 行 | 第一次走 getBean,才会真正 create |
创建 | AbstractAutowireCapableBeanFactory#doCreateBean |
594 行 | 实例化 + 属性赋值 + 初始化 |
缓存 | DefaultSingletonBeanRegistry#addSingleton |
153 行 | 创建完后放进 ConcurrentHashMap singletonObjects |
懒加载(
@Lazy(true)
)的 Bean 不会在这一步创建,而是第一次getBean
时才触发。
4. 源码片段速读
4.1 只关心单例、非懒加载
java
// DefaultListableBeanFactory#preInstantiateSingletons
for (String beanName : beanDefinitionNames) {
RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
getBean(beanName); // 就是这一行触发创建
}
}
4.2 真正的创建逻辑
java
// AbstractAutowireCapableBeanFactory#doCreateBean
instanceWrapper = createBeanInstance(beanName, mbd, args); // ① 实例化
populateBean(beanName, mbd, instanceWrapper); // ② 依赖注入
exposedObject = initializeBean(beanName, exposedObject, mbd); // ③ 初始化
4.3 初始化里干了啥?
java
// initializeBean 内部顺序
invokeAwareMethods(beanName, bean); // BeanNameAware 等
wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
invokeInitMethods(beanName, wrappedBean, mbd); // @PostConstruct → InitializingBean → 自定义 init-method
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
最后一步如果开启 AOP,会在这里返回代理对象。
5. 三级缓存与循环依赖(面试高频)
Spring 为了解决 单例循环依赖 ,在 doCreateBean
里引入三级缓存:
缓存 | 数据结构 | 作用 |
---|---|---|
singletonObjects | ConcurrentHashMap |
成品 Bean |
earlySingletonObjects | ConcurrentHashMap |
早期引用(已实例化但未初始化) |
singletonFactories | ConcurrentHashMap<String, ObjectFactory<?>> |
工厂对象,可生成代理 |
流程:
- 实例化后,先把工厂放进
singletonFactories
- 如果发生循环依赖,提前执行工厂拿到引用,塞进
earlySingletonObjects
- 初始化完成后,升级成正式 Bean,放入
singletonObjects
,清理其它两级。
6. 懒加载、原型、Bean 的区分
类型 | 何时创建 |
---|---|
singleton + 非懒加载 | finishBeanFactoryInitialization() 阶段统一创建 |
singleton + 懒加载 | 第一次 getBean 才创建 |
prototype | 每次 getBean 都重新 doCreateBean |
request/session | WebApplicationContext 中对应作用域第一次访问时创建 |
7. 调试技巧一条命令
把日志开到 DEBUG,一眼看全:
yaml
logging:
level:
org.springframework.beans.factory.support.DefaultListableBeanFactory: DEBUG
org.springframework.beans.factory.support.AbstractBeanFactory: DEBUG
启动后你会看到:
arduino
Creating instance of bean 'userService'
Finished creating instance of bean 'userService'
8. 小结
- 注册 :
@ComponentScan
等把类变成BeanDefinition
→ Map - 实例化 :
refresh()
末尾的preInstantiateSingletons()
统一遍历,首次getBean
才doCreateBean
- 三级缓存:解决循环依赖,同时支持 AOP 提前代理
- 懒加载 / 原型:各自在第一次使用时才走创建链路
java
getBean(beanName); // 没有就创建,创建完就放缓存