Spring启动阶段发生什么
Spring 启动阶段概述
- 定义:
- Spring 启动阶段是指 Spring 应用程序上下文(
ApplicationContext
)初始化并准备好所有 Bean 的过程,通常在 Spring 或 Spring Boot 应用启动时发生。 - 目的:
- 初始化 IoC 容器,加载配置,创建并管理 Bean,完成依赖注入,准备应用程序运行环境。
- 场景:
- Spring 应用通过
main
方法或容器(如 Tomcat)启动。 - Spring Boot 应用通过
SpringApplication.run()
。
核心点
- Spring 启动涉及容器初始化、Bean 定义加载、Bean 创建和扩展点执行,基于 IoC 和 AOP 机制。
1. Spring 启动阶段详细过程
Spring 启动阶段主要发生在 ApplicationContext
初始化过程中,以下按步骤拆解(以 AnnotationConfigApplicationContext
或 Spring Boot 为例):
(1) 容器初始化
- 描述:
- 创建
ApplicationContext
实例,初始化核心组件。 - 细节:
- Spring 核心:
- 创建
DefaultListableBeanFactory
(默认 Bean 工厂)。 - 初始化
BeanDefinitionRegistry
,用于存储 Bean 定义。
- 创建
- Spring Boot 核心:
SpringApplication.run()
创建AnnotationConfigApplicationContext
。- 加载
META-INF/spring.factories
中的自动配置类。
- 源码:
AbstractApplicationContext.<init>
:初始化工厂和环境。SpringApplication.prepareContext
:设置上下文。
(2) 环境准备
- 描述:
- 配置应用程序环境,如属性文件、环境变量。
- 细节:
- 加载
application.properties
或application.yml
。 - 设置
Environment
(ConfigurableEnvironment
),支持 profile(如dev
、prod
)。 - Spring Boot 额外加载命令行参数和默认属性。
- 示例:
spring.profiles.active=dev
server.port=8080
- 源码:
ConfigurableEnvironment.prepare
:加载属性源。SpringApplication.prepareEnvironment
。
(3) Bean 定义加载
- 描述:
- 扫描并注册所有 Bean 定义(
BeanDefinition
),描述 Bean 的元信息(如类名、作用域)。 - 细节:
- 注解方式:
- 扫描
@ComponentScan
指定的包,识别@Component
、@Service
、@Controller
等。 - 解析
@Configuration
和@Bean
。
- 扫描
- XML 方式:
- 解析
<bean>
标签。
- 解析
- Spring Boot:
- 加载
@SpringBootApplication
(包含@ComponentScan
和@EnableAutoConfiguration
)。 - 自动配置(如
DataSourceAutoConfiguration
)。
- 加载
- 示例:
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
- 源码:
ClassPathBeanDefinitionScanner.scan
:扫描注解。ConfigurationClassPostProcessor.postProcessBeanDefinitionRegistry
:处理配置类。
(4) BeanFactory 后处理
- 描述:
- 执行
BeanFactoryPostProcessor
,修改 Bean 定义或添加新定义。 - 细节:
- 常见处理器:
ConfigurationClassPostProcessor
(解析@Configuration
)。 - Spring Boot 使用
PropertySourcesPlaceholderConfigurer
解析${}
占位符。 - 示例:
@Bean
public DataSource dataSource() {
return new DriverManagerDataSource("${db.url}");
}
- 源码:
AbstractApplicationContext.invokeBeanFactoryPostProcessors
。
(5) Bean 实例化与初始化
- 描述:
- 创建 Bean 实例,完成依赖注入和初始化。
- 子步骤:
- 实例化:
- 通过反射(
newInstance
)创建 Bean。
- 通过反射(
- 属性注入:
- 填充
@Autowired
或 XML 定义的依赖。
- 填充
- BeanPostProcessor 前置处理:
- 执行
postProcessBeforeInitialization
(如 AOP 代理生成)。
- 执行
- 初始化:
- 调用
Aware
接口(如ApplicationContextAware
)。 - 执行
@PostConstruct
或InitializingBean.afterPropertiesSet
。 - 调用
init-method
。
- 调用
- BeanPostProcessor 后置处理:
- 执行
postProcessAfterInitialization
(如完成代理)。
- 执行
- 循环依赖处理:
- 使用 三级缓存:
- 一级:
singletonObjects
(完成 Bean)。 - 二级:
earlySingletonObjects
(早期 Bean)。 - 三级:
singletonFactories
(工厂)。
- 一级:
- 示例:
@Component
public class MyBean implements InitializingBean {
@Autowired
private OtherBean otherBean;
@PostConstruct
public void init() {
System.out.println("PostConstruct");
}
@Override
public void afterPropertiesSet() {
System.out.println("InitializingBean");
}
}
- 源码:
AbstractAutowireCapableBeanFactory.createBean
:创建 Bean。DefaultSingletonBeanRegistry.getSingleton
:处理循环依赖。
(6) 事件发布与监听
- 描述:
- 发布容器事件,触发监听器。
- 细节:
- 发布事件:
ContextRefreshedEvent
(容器刷新完成)。 - Spring Boot 额外发布
ApplicationStartedEvent
等。 - 监听器:通过
@EventListener
或ApplicationListener
实现。 - 示例:
@Component
public class MyListener {
@EventListener
public void onContextRefreshed(ContextRefreshedEvent event) {
System.out.println("Context refreshed");
}
}
- 源码:
AbstractApplicationContext.publishEvent
。
(7) 容器刷新完成
- 描述:
- 容器完成初始化,所有单例 Bean 就绪。
- 细节:
- 单例 Bean 存入
singletonObjects
。 - Spring Boot 启动嵌入式服务器(如 Tomcat)。
- 源码:
AbstractApplicationContext.refresh
:核心启动方法。
(8) 扩展:Spring Boot 特有
- 自动配置:
- 加载
spring.factories
中的AutoConfiguration
类。 - 按条件(
@Conditional
)启用配置。 - Banner 打印:
- 显示启动横幅。
- Actuator 暴露:
- 启用监控端点(如
/actuator/health
)。 - 源码:
SpringApplication.run
:入口。AutoConfigurationImportSelector
:加载自动配置。
2. 启动阶段流程图
1. 容器初始化
↓
2. 环境准备
↓
3. Bean 定义加载
↓
4. BeanFactory 后处理
↓
5. Bean 实例化与初始化
↓
6. 事件发布
↓
7. 刷新完成
3. 关键机制
- IoC 容器:
DefaultListableBeanFactory
管理 Bean。- AOP 集成:
BeanPostProcessor
生成代理(如@Transactional
)。- 循环依赖:
- 三级缓存解决单例 Bean 依赖。
- 事件驱动:
ApplicationEvent
和ApplicationListener
解耦组件。- 自动配置:
- Spring Boot 通过条件注解简化配置。
4. 常见问题
- 启动慢:
- 原因:扫描包过多、自动配置复杂。
- 解决:缩小
@ComponentScan
范围,禁用不必要配置。 - 循环依赖:
- 原因:Bean 相互注入。
- 解决:用
@Lazy
或构造器注入。 - Bean 未加载:
- 原因:包未扫描、条件不满足。
- 解决:检查
@ComponentScan
或@Conditional
。
5. 面试角度
- 问“过程”:
- 提 7 大步骤,重点 Bean 定义和初始化。
- 问“机制”:
- 提 IoC、AOP、三级缓存。
- 问“Spring Boot”:
- 提自动配置和事件。
- 问“问题”:
- 提循环依赖、启动慢。
6. 总结
Spring 启动阶段通过 ApplicationContext
初始化容器,加载环境、Bean 定义,创建并初始化 Bean,发布事件,最终准备运行环境。核心是 IoC 和 AOP,Spring Boot 增加自动配置和嵌入式服务器。面试可提流程、源码或问题解决,清晰展示理解。
如果您想深入某部分(如 refresh
源码或自动配置),请告诉我,我可以进一步优化!