请描述 Spring 容器从启动到就绪的完整流程,涵盖 Bean 的加载、初始化以及关键扩展点的触发顺序。
考察说明
考查对 Spring IoC 容器启动生命周期及核心扩展机制的理解。
回答思路
- 【回答框架 1】Spring 容器启动入口是 AbstractApplicationContext 的 refresh() 方法,它定义了整个启动流程的骨架。整个过程大致分为:配置元数据解析、BeanFactory 准备、Bean 定义注册、Bean 实例化与初始化、以及内置单例的预实例化。
- 【回答框架 2】流程始于 prepareRefresh() 和 obtainFreshBeanFactory(),前者做环境准备,后者负责解析配置(XML/注解)并注册 BeanDefinition。随后 prepareBeanFactory() 为容器配置默认类加载器、SpEL 解析器等基础设施。
- 【回答框架 3】核心阶段是 invokeBeanFactoryPostProcessors() 和 registerBeanPostProcessors(),前者处理 BeanFactoryPostProcessor(如配置类解析、占位符替换),后者注册 BeanPostProcessor,为后续 Bean 初始化提供钩子。
- 【回答框架 4】接下来是实例化阶段:finishBeanFactoryInitialization() 会实例化所有非懒加载的单例 Bean,按依赖顺序创建。每个 Bean 的创建过程包括实例化、属性填充、Aware 回调、BeanPostProcessor 前置处理、初始化方法(init-method / InitializingBean)以及后置处理。
- 【回答框架 5】最后 finishRefresh() 发布 ContextRefreshedEvent 事件,启动内置 Web 服务器(若为 Web 应用)并完成容器的生命周期管理。
- 【关键点 1】refresh() 方法是 Spring 容器启动的核心入口,定义了标准流程。
- 【关键点 2】BeanDefinition 注册与解析发生在实例化之前。
- 【关键点 3】BeanFactoryPostProcessor 先于 BeanPostProcessor 执行。
- 【关键点 4】单例 Bean 在 finishBeanFactoryInitialization() 中预先实例化。
- 【关键点 5】整个流程通过事件发布(如 ContextRefreshedEvent)支持扩展。
- 【易错点 1】混淆 BeanFactoryPostProcessor 和 BeanPostProcessor 的执行时机,前者用于修改 Bean 定义,后者用于修改 Bean 实例。
- 【易错点 2】忽略 Bean 的初始化顺序依赖,可能因循环依赖或懒加载导致启动异常。
- 【易错点 3】在扩展点中做耗时操作会拖慢启动速度。