Spring 框架的启动过程较为复杂,涉及容器初始化、Bean 加载与创建等多个关键环节,以下从 Spring 框架(以传统 Spring 应用,如基于 ClassPathXmlApplicationContext
为例) 和 Spring Boot 应用 两个维度,详细拆解启动流程:
一、传统 Spring 应用(基于 XML 配置,如 ClassPathXmlApplicationContext
)
以手动创建 ClassPathXmlApplicationContext
加载 XML 配置为例,核心流程如下:
1. 初始化准备阶段
- 入口触发:开发者通过
new ClassPathXmlApplicationContext("applicationContext.xml")
显式启动 Spring 容器。 - 资源定位:根据传入的 XML 路径(如
applicationContext.xml
),Spring 会扫描类路径,定位到配置文件资源。
2. 容器创建与准备
- 创建
BeanFactory
:
内部会初始化DefaultListableBeanFactory
(Spring 核心 Bean 工厂实现),作为后续管理 Bean 的基础容器,负责 Bean 的注册、解析和创建。 - 加载配置元数据:
通过XmlBeanDefinitionReader
解析 XML 配置文件,将<bean>
标签、<context:component-scan>
等配置,转化为BeanDefinition
(Bean 的“定义元数据”,包含类名、作用域、依赖等信息),并注册到BeanFactory
中。
3. Bean 工厂后置处理(BeanFactoryPostProcessor
)
- 执行时机:在 Bean 实例化前,对
BeanFactory
中的BeanDefinition
进行修改或增强。 - 典型应用:
PropertyPlaceholderConfigurer
:替换BeanDefinition
中的属性占位符(如${db.url}
),加载外部配置(.properties 文件)。ConfigurationClassPostProcessor
(若使用@Configuration
注解):解析 Java 配置类,补充BeanDefinition
。
4. Bean 后置处理器注册(BeanPostProcessor
)
- 作用:在 Bean 实例化、初始化前后插入自定义逻辑(如属性注入、AOP 代理)。
- 注册方式:Spring 会扫描
BeanFactory
中已注册的BeanPostProcessor
类型的 BeanDefinition,提前实例化这些处理器,供后续 Bean 生命周期使用。
5. Bean 实例化与依赖注入
- 触发条件:
- 对于非懒加载(
lazy-init="false"
)的单例 Bean,Spring 会在容器启动阶段主动实例化; - 懒加载 Bean 会延迟到第一次被使用时实例化。
- 对于非懒加载(
- 核心流程:
- 实例化:通过反射创建 Bean 对象(调用构造器)。
- 属性注入(DI):根据
BeanDefinition
中的依赖信息(如@Autowired
、<property>
),从BeanFactory
中查找依赖的 Bean 并注入。 - 初始化前(
BeanPostProcessor.postProcessBeforeInitialization
):执行自定义增强(如修改 Bean 属性)。 - 初始化(
InitializingBean.afterPropertiesSet
或自定义init-method
):执行 Bean 初始化逻辑。 - 初始化后(
BeanPostProcessor.postProcessAfterInitialization
):典型应用是 AOP 代理(如AnnotationAwareAspectJAutoProxyCreator
会在此阶段为 Bean 创建代理对象)。
6. 容器启动完成
- 所有非懒加载单例 Bean 完成实例化、依赖注入和初始化后,
ApplicationContext
进入“就绪”状态,可对外提供 Bean 的获取与使用。
二、Spring Boot 应用(自动装配简化流程)
Spring Boot 基于“约定优于配置”,通过自动装配大幅简化启动流程,核心流程如下:
1. 启动类触发(@SpringBootApplication
)
- 入口:
SpringApplication.run(MyApplication.class, args)
,其中@SpringBootApplication
是复合注解,包含:@Configuration
:标记类为配置类,参与 Bean 定义扫描。@ComponentScan
:扫描当前包及子包下的@Component
、@Service
等组件。@EnableAutoConfiguration
:开启自动装配,触发spring.factories
中配置的自动配置类。
2. 初始化 SpringApplication
- 核心准备:
- 推断应用类型(Servlet/WebFlux/Reactive);
- 加载
ApplicationContextInitializer
(用于提前初始化容器); - 加载
ApplicationListener
(监听启动事件,如ApplicationStartingEvent
)。
3. 环境准备(Environment
)
- 作用:加载外部配置(如
application.yml
、系统属性、环境变量等),并将配置整合到Environment
中,供后续流程使用。 - 扩展点:
EnvironmentPostProcessor
可自定义环境配置(如加载额外配置文件)。
4. 创建 ApplicationContext
- 类型选择:根据应用类型(Servlet 环境默认创建
AnnotationConfigServletWebServerApplicationContext
)创建对应的ApplicationContext
。 - 与传统 Spring 衔接:内部依然依赖
DefaultListableBeanFactory
管理 Bean,但通过注解驱动替代 XML 解析。
5. 自动装配(@EnableAutoConfiguration
)
- 核心逻辑:
Spring Boot 会读取META-INF/spring.factories
中EnableAutoConfiguration
对应的配置类(如DataSourceAutoConfiguration
、WebMvcAutoConfiguration
等),将这些配置类的BeanDefinition
注册到容器。 - 条件装配:通过
@Conditional
系列注解(如@ConditionalOnClass
、@ConditionalOnBean
),判断是否满足装配条件,避免无效 Bean 加载。
6. Bean 加载与初始化(同传统 Spring 核心流程)
- 扫描
@ComponentScan
路径下的组件(@Service
、@Controller
等),结合自动装配的BeanDefinition
,执行 Bean 实例化、依赖注入、初始化 流程,最终完成容器启动。
7. Web 服务器启动(Servlet 环境)
- 若为 Web 应用,
ServletWebServerApplicationContext
会触发TomcatWebServer
(或其他嵌入式服务器)的启动,绑定端口并初始化 Servlet 容器,使应用具备 HTTP 服务能力。
8. 发布启动事件
- 容器启动完成后,发布
ApplicationReadyEvent
,通知监听者(如自定义ApplicationListener
)应用已就绪,可处理外部请求。
三、核心区别与总结
对比维度 | 传统 Spring 应用 | Spring Boot 应用 |
---|---|---|
配置方式 | 依赖 XML 或手动 Java 配置 | 注解驱动 + 自动装配,简化配置 |
启动入口 | 手动创建 ApplicationContext | SpringApplication.run() 统一入口 |
核心流程 | 显式解析配置 → Bean 工厂初始化 → Bean 实例化 | 自动装配 + 条件化配置,弱化 XML 依赖 |
Web 支持 | 需手动集成 Servlet 容器(如 Tomcat) | 自动嵌入 Web 服务器(Tomcat/Undertow 等) |
本质共性:无论传统 Spring 还是 Spring Boot,核心都是围绕 BeanFactory
管理 Bean 生命周期,通过 AOP 实现事务、代理,通过 DI 完成依赖注入。Spring Boot 本质是“更智能的 Spring 封装”,通过自动装配和约定简化了配置与启动流程,但底层逻辑与传统 Spring 一脉相承。
理解启动流程后,可更清晰排查问题(如 Bean 未加载、自动装配失效),也能合理扩展(如自定义 BeanFactoryPostProcessor
、ApplicationContextInitializer
干预启动过程)。