Spring容器的启动流程可以看作是一个精密的装配流水线,其核心目标是根据用户提供的配置元数据(Configuration Metadata),创建、配置并组装应用程序中的对象(Bean),最终形成一个完整的、可用的应用上下文(ApplicationContext)

下面我将从宏观流程核心步骤两个层面,并结合关键的源码接口,来详细解释Spring容器的启动流程。


一、宏观流程概述

一个典型的Spring容器(以ClassPathXmlApplicationContext为例)启动流程可以概括为以下三个大阶段:

  1. 容器初始化阶段:为启动做准备,设置环境变量、资源解析器等。
  2. Bean加载与解析阶段(核心中的核心):读取配置元数据,将其解析为容器内部数据结构(BeanDefinition)。
  3. Bean实例化与依赖注入阶段:根据BeanDefinition的信息,通过反射创建Bean实例,并解决其依赖关系。
  4. 后处理与完成阶段:执行相关的后处理器,触发生命周期回调,发布上下文就绪事件。

为了更直观地理解,下图描绘了这个过程的核心步骤与迭代循环:

flowchart TD
    A[Spring容器启动流程] --> B[初始化阶段
创建Context、加载配置] B --> C[加载与解析阶段
读取配置→BeanDefinition] C --> D[实例化与注入阶段
(核心循环开始)] subgraph D [Bean创建循环] D1[实例化 Bean
(调用构造函数)] D2[填充属性
(依赖注入)] D3[处理 Aware 接口] D4[BeanPostProcessor前置处理] D5[初始化方法
(InitializingBean, init-method)] D6[BeanPostProcessor后置处理
(AOP在此发生)] end D --> E[所有单例Bean创建完成?] E -- 否 --> D E -- 是 --> F[完成阶段
发布ContextRefreshedEvent] F --> G[应用运行
容器就绪]

二、详细核心步骤分解(以AnnotationConfigApplicationContext为例)

让我们沿着图中所示的流程,深入每个步骤的细节。

阶段一:容器初始化

  • 入口:调用ApplicationContext的构造方法,例如new AnnotationConfigApplicationContext(AppConfig.class)
  • 动作
    1. 实例化一个AnnotatedBeanDefinitionReader,它知道如何解析带有@Configuration@Component等注解的类。
    2. 实例化一个ClassPathBeanDefinitionScanner,用于扫描类路径下的组件(如果配置了组件扫描)。
    3. 调用register(componentClasses),将配置类注册到容器中。此时,配置类本身也被注册为一个BeanDefinition

阶段二:Bean加载与解析(refresh()方法)

调用ApplicationContextrefresh()方法是整个启动流程的核心入口和总指挥。这个方法定义在ConfigurableApplicationContext接口中,包含了启动、刷新、停止容器的完整生命周期。以下是refresh()方法中最重要的11个步骤:

  1. prepareRefresh() - 准备刷新

    • 设置容器的启动日期和活跃状态。
    • 初始化占位符属性源(Property Sources)。
    • 验证所有必需的属性是否可解析。
  2. obtainFreshBeanFactory() - 获取BeanFactory

    • 对于AnnotationConfigApplicationContext:刷新或创建一个新的GenericApplicationContext内部持有的DefaultListableBeanFactory。这是Bean定义注册和管理的核心容器。
    • 对于ClassPathXmlApplicationContext:会在这里创建一个新的BeanFactory(通常是DefaultListableBeanFactory),然后调用loadBeanDefinitions(beanFactory)来通过XmlBeanDefinitionReader加载和解析XML文件。
  3. prepareBeanFactory(beanFactory) - 准备BeanFactory

    • 配置BeanFactory的标准上下文特性,如ClassLoaderSpEL表达式解析器、属性编辑器注册器等。
    • 添加一些内置的BeanPostProcessor,例如ApplicationContextAwareProcessor,用于处理各种*Aware接口。
  4. postProcessBeanFactory(beanFactory) - 后处理BeanFactory(扩展点)

    • 这是一个空的模板方法,允许子类在Bean定义加载完成之前,对BeanFactory进行进一步的定制和扩展。例如,WebApplicationContext会在这里添加Servlet相关的Scope。
  5. invokeBeanFactoryPostProcessors(beanFactory) - 执行BeanFactoryPostProcessor

    • 这是非常关键的一步。它会实例化并调用所有BeanFactoryPostProcessorBeanDefinitionRegistryPostProcessor
    • 这些处理器允许在Bean实例化之前修改应用程序上下文的Bean定义(即修改BeanDefinition)。
    • 常见例子
      • ConfigurationClassPostProcessor:处理@Configuration类,解析其中的@Bean@Import@ComponentScan等注解,并将扫描到的Bean注册到容器中。这是注解驱动配置的核心
      • PropertySourcesPlaceholderConfigurer:处理占位符${...},从属性文件中加载值。
  6. registerBeanPostProcessors(beanFactory) - 注册BeanPostProcessor

    • 实例化、注册所有BeanPostProcessor。注意,此时只是注册,调用发生在Bean实例化过程中
    • BeanPostProcessor是Bean的后置处理器,在Bean的初始化方法调用前后进行拦截,可以修改或包装Bean实例。AOP的动态代理就是通过AnnotationAwareAspectJAutoProxyCreator(它是一个BeanPostProcessor)在这里被注册,并在后续步骤中生效的。
  7. initMessageSource() - 初始化消息源

    • 初始化MessageSource组件,用于国际化(i18n)消息处理。
  8. initApplicationEventMulticaster() - 初始化事件广播器

    • 初始化事件广播器(ApplicationEventMulticaster),用于支持Spring的事件发布-订阅模型。
  9. onRefresh() - 模板方法(扩展点)

    • 又一个空的模板方法,允许特定的上下文子类初始化其他特殊的Bean。例如,Spring Boot的EmbeddedWebApplicationContext会在这里创建内嵌的Web服务器(Tomcat, Jetty)。
  10. registerListeners() - 注册监听器

    • 将实现了ApplicationListener接口的监听器Bean注册到前面初始化的事件广播器中。
    • 也会发布那些在早期步骤中产生的“早期应用事件”。

阶段三:Bean实例化与依赖注入

  1. finishBeanFactoryInitialization(beanFactory) - 完成BeanFactory的初始化(实例化所有非懒加载的单例Bean)
    • 这是另一个最核心的步骤。容器会在这里预实例化所有单例且非懒加载的Bean
    • 流程(即Bean的生命周期)对于每一个Bean如下:
      • 实例化(Instantiate):通过反射(通常是无参或有参构造器)创建Bean的实例。
      • 填充属性(Populate properties):根据配置(如@Autowired, @Value)进行依赖注入(Dependency Injection, DI)。
      • 处理Aware接口:如果Bean实现了各种Aware接口(如BeanNameAware, BeanFactoryAware, ApplicationContextAware),则调用其setter方法注入相关对象。
      • BeanPostProcessor.postProcessBeforeInitialization():在初始化方法调用前,执行所有BeanPostProcessor的预处理。
      • 初始化(Initialize)
        • 如果Bean实现了InitializingBean接口,调用其afterPropertiesSet()方法。
        • 调用自定义的初始化方法(通过@Bean(initMethod="...")或XML中的init-method指定)。
      • BeanPostProcessor.postProcessAfterInitialization():在初始化方法调用后,执行所有BeanPostProcessor的后处理。AOP代理就是在此处生成的! 如果发现有切面匹配这个Bean,则会返回一个代理对象来包装目标Bean。
      • 此时,一个完整的、经过所有处理的Bean就已经存在于容器中了。

阶段四:完成与发布

  1. finishRefresh() - 完成刷新

    • 初始化生命周期处理器(LifecycleProcessor)。
    • 发布容器刷新事件ContextRefreshedEvent),通知所有监听器容器已经准备就绪。
    • 调用生命周期处理器的onRefresh()方法。
  2. 容器运行

    • 此时,Spring容器已经完全启动,所有单例Bean都已创建并装配完毕,应用程序可以正常运行。可以通过context.getBean(...)来获取Bean并使用。

三、总结与关键点

  • refresh()方法是核心:它驱动了整个容器的启动流程。
  • BeanDefinition是蓝图:容器并不直接处理你的Bean类,而是先将其解析为内部的BeanDefinition数据结构。
  • 扩展点无处不在
    • BeanFactoryPostProcessor:修改Bean的定义(配置元数据)。
    • BeanPostProcessor:修改Bean的实例(包装、代理等)。
    • 各种Aware接口:让Bean能感知到容器。
  • Bean的生命周期是复杂的:从定义到可用,经历了构造、注入、aware回调、init方法、前后置处理等多个步骤。
  • AOP代理发生得较晚:它是在Bean实例化、属性注入之后,通过BeanPostProcessor在初始化阶段后期生成的。