SpringBoot面试题10-IOC容器的初始化流程
一、IOC容器初始化流程一览


二、详解
2-1、一句话总览
IOC 容器初始化流程,就是 Spring 将项目中的类解析成 BeanDefinition,创建 BeanFactory,再通过刷新容器(refresh)真正创建 Bean 并完成依赖注入的过程。
2-2、全流程结构图
(1)准备阶段:读取配置、扫描类、注册 BeanDefinition
(2)构造容器:创建 BeanFactory、准备 BeanFactory
(3)刷新容器:真正创建 Bean、注入依赖、AOP、初始化等
2-3、详细步骤
阶段一:准备阶段(加载配置信息 → 转成 BeanDefinition)
| 步骤 | 专业词 | 小白理解 |
|---|---|---|
| 1. 解析配置源 | XML / 注解 / 配置类 | 读“计划书” |
| 2. 组件扫描 | @ComponentScan | 找出“要管理的类” |
| 3. 解析类信息 | BeanDefinitionReader | 把类的信息转成可存储结构 |
| 4. 注册 BeanDefinition | BeanDefinitionRegistry | 把“类的说明书”存到容器里 |
注意:此时 Bean 还没有创建,只是把“要创建什么 Bean”全记录下来了。
你可以理解为:先建立员工档案,还没招人。
阶段二:构造容器(获得 BeanFactory 并做准备)
IOC 容器的核心是 BeanFactory。
| 步骤 | 小白理解 |
|---|---|
| 1. 创建 BeanFactory | 开一个仓库 |
| 2. BeanFactoryPostProcessor 执行 | 调整“档案”/补充配置 |
| 3. 注册 BeanPostProcessor | 准备“加工规则”(AOP 就靠这个) |
重点:AOP 和依赖注入的“钩子点”都是在这注册的。
就像厨房先准备锅碗调料,不做菜但把环境准备好。
阶段三:刷新容器 refresh()(真的开始创建 Bean)⭐
这是 IOC 初始化中最重要的核心步骤。
| 顺序 | 看起来的事情 | 实际发生的机制 |
|---|---|---|
| 1. 实例化 Bean | new 出对象 | 构造器执行 |
| 2. 依赖注入 | @Autowired | 通过 BeanFactory 递归注入 |
| 3. 执行 BeanPostProcessor 前置 | AOP 动态代理发生在这里 | JDK / CGLIB 代理生成 |
| 4. 调用初始化方法 | @PostConstruct / InitializingBean | 让 Bean 做初始化工作 |
| 5. 执行 BeanPostProcessor 后置 | Bean 最终定型 | 再次增强或包装 |
这个阶段才是 IOC 真正“把人招进来并分工上岗”的过程。
【注意】:
此时,实例化的是非懒加载的单例bean,多例bean和懒加载的bean不会在这个阶段实例化,将来用到的时候再创建。
2-4、最后启动 Web 容器(如果是 SpringBoot)
如果是 Web 项目,会再启动:
Tomcat / Jetty / Undertow
然后项目开始对外提供服务。
2-5、小结
IOC 初始化分为三个阶段:
第一阶段,加载配置并扫描组件,将类解析成 BeanDefinition,注册到容器中,但此时不创建对象。
第二阶段,创建 BeanFactory 并执行 BeanFactoryPostProcessor,注册 BeanPostProcessor,完成容器的准备工作。
第三阶段调用 refresh,真正创建 Bean:先实例化,再依赖注入,然后执行 BeanPostProcessor(AOP 代理就是在这产生),最后执行初始化方法,完成整个 Bean 生命周期。
最终,如果是 Web 应用,再启动内置服务器对外提供服务。
三、BeanFactoryPostProcessor 和 BeanPostProcessor
这两个名字很像,但作用、触发时机、能做的事情完全不同。
3-1、一句话总结它们的区别
- BeanFactoryPostProcessor:在 Bean 创建之前,用来修改 Bean 的配置信息(BeanDefinition)。
- BeanPostProcessor:在 Bean 创建之后,用来修改 Bean 实例本身(可以做 AOP)。
像这样记:
| 名字 | 时机 | 作用对象 | 常用用途 | 关键点 |
|---|---|---|---|---|
| BeanFactoryPostProcessor | Bean 未创建前 | BeanDefinition(配方) | 修改 Bean 配置、属性值 | 动 Bean 的“说明书” |
| BeanPostProcessor | Bean 已创建后 | Bean 实例(成品) | AOP 增强、注解处理等 | 动 Bean “成品本身” |
3-2、深入理解
1) BeanFactoryPostProcessor
触发时机
发生在 容器启动时,Bean 创建之前。
能做什么?
→ 修改 BeanDefinition
比如:
-
给 Bean 自动加属性
-
替换 Bean 的依赖
-
动态修改构造参数
-
通过它才能做到 @Value、占位符解析(
PropertySourcesPlaceholderConfigurer)
典型代码框架
public class MyBFPP implements BeanFactoryPostProcessor {
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
BeanDefinition bd = beanFactory.getBeanDefinition("myService");
bd.getPropertyValues().add("name", "ChangedName");
}
}
2) BeanPostProcessor
触发时机
Bean 已经 new 出来,并且依赖注入完成以后:
构造器 → 依赖注入 → (这里) before → 初始化 → after
能做什么?
→ 可以操作 Bean 实例本身,尤其是:
-
AOP 动态代理 就是在这里实现(非常重要)
-
@Autowired、@Resource 注入处理也是通过它实现
-
@PostConstruct 生命周期回调也是它触发
常见方法
public class MyBPP implements BeanPostProcessor {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) {
System.out.println("初始化之前: " + beanName);
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) {
System.out.println("初始化之后: " + beanName);
return bean;
}
}
3-3、关键结合点 —— AOP 为什么靠 BeanPostProcessor?
因为 AOP 是给 Bean 换成代理对象,必须在 Bean 已经被实例化之后才能替换。
所以 AOP 的核心类 AnnotationAwareAspectJAutoProxyCreator 就是一个 BeanPostProcessor。
你如果理解了这句,你就真正理解了 Spring:
AOP = BeanPostProcessor 在 Bean 初始化后,返回代理对象进行替换。
3-4、小结
BeanFactoryPostProcessor 用来在 Bean 实例创建之前,操作 BeanDefinition。
典型用途是修改 Bean 的配置,比如 PropertySourcesPlaceholderConfigurer 解析配置文件。
BeanPostProcessor 则发生在 Bean 创建之后,用来对 Bean 对象本身进行增强,
AOP 动态代理就是通过 BeanPostProcessor 在 postProcessAfterInitialization 阶段将原始对象替换为代理对象实现的。
更多推荐

所有评论(0)