Skip to content

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.propertiesapplication.yml
  • 设置 EnvironmentConfigurableEnvironment),支持 profile(如 devprod)。
  • 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)。
    • 执行 @PostConstructInitializingBean.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 等。
  • 监听器:通过 @EventListenerApplicationListener 实现。
  • 示例
@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 依赖。
  • 事件驱动
  • ApplicationEventApplicationListener 解耦组件。
  • 自动配置
  • 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 源码或自动配置),请告诉我,我可以进一步优化!