Spring源码又看了一遍

8 阅读5分钟

Spring IoC 容器从启动到完成 Bean 的创建和注入,涉及一系列精密的步骤。下面结合源码(以 AnnotationConfigApplicationContext 为例)详细拆解整个过程,并说明每个环节的作用。


一、容器启动入口

通常我们使用以下代码启动基于注解的 IoC 容器:

java

ApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);

AnnotationConfigApplicationContext 的构造方法最终会调用 refresh(),这是 IoC 容器初始化的核心方法,定义在 AbstractApplicationContext 中。

java

public AnnotationConfigApplicationContext(Class<?>... componentClasses) {
    this();
    register(componentClasses);
    refresh();  // 关键入口
}

二、refresh() 核心步骤(源码级)

AbstractApplicationContext.refresh() 是整个 IoC 容器启动的模板方法,主要包含以下步骤(以 Spring 5.x 为例):

java

@Override
public void refresh() throws BeansException, IllegalStateException {
    synchronized (this.startupShutdownMonitor) {
        // 1. 准备刷新上下文
        prepareRefresh();

        // 2. 获取 BeanFactory(如果已有则刷新,否则创建)
        ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

        // 3. 为 BeanFactory 设置容器级别的功能(类加载器、后处理器等)
        prepareBeanFactory(beanFactory);

        try {
            // 4. 允许子类对 BeanFactory 进行后处理(如添加 BeanPostProcessor)
            postProcessBeanFactory(beanFactory);

            // 5. 调用 BeanFactoryPostProcessor 的 postProcessBeanFactory 方法
            invokeBeanFactoryPostProcessors(beanFactory);

            // 6. 注册 BeanPostProcessor(在 Bean 创建前后起作用)
            registerBeanPostProcessors(beanFactory);

            // 7. 初始化国际化资源等
            initMessageSource();

            // 8. 初始化事件广播器
            initApplicationEventMulticaster();

            // 9. 模板方法,供子类初始化特定 Bean(如 Web 容器中的 ServletContext)
            onRefresh();

            // 10. 注册事件监听器
            registerListeners();

            // 11. 完成 BeanFactory 初始化,实例化所有非懒加载的单例 Bean
            finishBeanFactoryInitialization(beanFactory);

            // 12. 完成刷新,发布事件
            finishRefresh();
        } catch (BeansException ex) {
            // 异常处理,销毁已创建的 Bean
            destroyBeans();
            cancelRefresh(ex);
            throw ex;
        }
    }
}

下面分解每个步骤的职责和源码细节。


三、关键步骤详解

1. prepareRefresh()

  • 设置启动时间、激活标志、初始化属性源(如系统环境变量、JVM 属性)。
  • 校验必要的属性是否存在。

2. obtainFreshBeanFactory()

  • 对于 AnnotationConfigApplicationContext,实际上已经在构造时创建了 DefaultListableBeanFactory,该方法只是返回它。
  • 对于 ClassPathXmlApplicationContext 等,会在此处加载 XML 配置并解析为 BeanDefinition

3. prepareBeanFactory(beanFactory)

  • 为 BeanFactory 添加基础功能:

    • 设置类加载器、表达式解析器(SpEL)。
    • 添加几个特殊的 BeanPostProcessor(如 ApplicationContextAwareProcessor)。
    • 忽略某些接口的自动装配(如 EnvironmentAware)。
    • 注册几个默认的 Bean(如 environmentsystemProperties)。

4. postProcessBeanFactory(beanFactory)

  • 模板方法,允许子类(如 AnnotationConfigApplicationContext)对 BeanFactory 进行额外处理。
  • 例如,AnnotationConfigApplicationContext 会在此处注册一个 ConfigurationClassPostProcessor(属于 BeanFactoryPostProcessor),用于处理 @Configuration 类。

5. invokeBeanFactoryPostProcessors(beanFactory)

  • 执行所有已注册的 BeanFactoryPostProcessor
  • 关键后处理器:ConfigurationClassPostProcessor,它扫描 @ComponentScan、解析 @Bean 等方法,将配置类中的定义转换为 BeanDefinition 并注册到容器。
  • 这一步后,容器拥有了所有 Bean 的 BeanDefinition

6. registerBeanPostProcessors(beanFactory)

  • 注册所有 BeanPostProcessor 实例,但不执行它们。这些处理器将在 Bean 实例化前后被调用。
  • 顺序:先注册 PriorityOrdered,再 Ordered,最后普通。
  • 重要内置处理器:AutowiredAnnotationBeanPostProcessor(处理 @Autowired@Value)、CommonAnnotationBeanPostProcessor(处理 @PostConstruct@PreDestroy)等。

7. initMessageSource()initApplicationEventMulticaster()onRefresh()registerListeners()

  • 这些步骤与国际化、事件机制相关,对 Bean 创建流程影响不大,略过。

8. finishBeanFactoryInitialization(beanFactory)

  • 最关键的一步:实例化所有非懒加载的单例 Bean
  • 调用 beanFactory.preInstantiateSingletons(),遍历所有 BeanDefinition,对单例且非懒加载的 Bean 执行 getBean() 触发创建。

getBean() 的深入调用链

getBean() → doGetBean() → 检查缓存 → 若未创建,则调用 createBean() → doCreateBean()
doCreateBean() 的主要步骤(在 AbstractAutowireCapableBeanFactory 中):

java

protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {
    // 1. 实例化 Bean(通过构造器或工厂方法)
    BeanWrapper instanceWrapper = createBeanInstance(beanName, mbd, args);
    Object bean = instanceWrapper.getWrappedInstance();

    // 2. 处理循环依赖:将 Bean 的早期引用暴露到三级缓存
    addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));

    // 3. 属性填充(依赖注入)
    populateBean(beanName, mbd, instanceWrapper);

    // 4. 初始化 Bean(执行各种 Aware 接口、BeanPostProcessor、init 方法)
    exposedObject = initializeBean(beanName, exposedObject, mbd);

    // 5. 注册销毁回调(如 @PreDestroy)
    registerDisposableBeanIfNecessary(beanName, bean, mbd);

    return exposedObject;
}

核心子步骤源码分析

3.1 createBeanInstance()

  • 根据 BeanDefinition 选择合适的实例化策略:

    • 如果定义了工厂方法,使用工厂方法。
    • 否则,通过构造器反射创建对象。若有多个构造器,根据参数匹配选择。

3.2 addSingletonFactory()

  • 将 Bean 的早期引用(尚未填充属性)放入三级缓存(singletonFactories),以便解决循环依赖。
  • 当其他 Bean 引用当前 Bean 时,可以从三级缓存中获取其早期引用。

3.3 populateBean()

  • 执行属性注入:

    • 处理 @Autowired@Resource@Value 等注解(通过 AutowiredAnnotationBeanPostProcessor)。
    • 处理 XML 配置中的 <property> 标签。
  • 通过 BeanPostProcessor 的 postProcessAfterInstantiation 钩子,允许修改属性注入前状态。

3.4 initializeBean()

  • 依次执行:

    1. 调用 Aware 方法(如 BeanNameAwareBeanFactoryAwareApplicationContextAware 等)。
    2. 执行 BeanPostProcessor 的 postProcessBeforeInitialization(如 @PostConstruct 在此阶段被调用)。
    3. 执行自定义 init-method 或 InitializingBean.afterPropertiesSet()
    4. 执行 BeanPostProcessor 的 postProcessAfterInitialization(AOP 代理在此生成,如 AnnotationAwareAspectJAutoProxyCreator)。

9. finishRefresh()

  • 发布 ContextRefreshedEvent,启动生命周期相关组件。

四、关键源码位置速查

步骤关键类关键方法
容器刷新AbstractApplicationContextrefresh()
BeanDefinition 注册ConfigurationClassPostProcessorpostProcessBeanDefinitionRegistry()
Bean 实例化AbstractAutowireCapableBeanFactorydoCreateBean()
依赖注入AbstractAutowireCapableBeanFactorypopulateBean()
循环依赖解决DefaultSingletonBeanRegistrygetSingleton()、三级缓存
初始化回调AbstractAutowireCapableBeanFactoryinitializeBean()
AOP 代理生成AbstractAutoProxyCreatorpostProcessAfterInitialization()

五、总结

Spring IoC 容器的启动过程可以概括为:

  1. 配置加载:通过 BeanDefinitionReader 读取配置,生成 BeanDefinition 并注册。
  2. 后处理器调用:执行 BeanFactoryPostProcessor 对 BeanDefinition 进行修改(如占位符替换、配置类解析)。
  3. 注册后处理器:注册 BeanPostProcessor,为 Bean 创建做好准备。
  4. Bean 创建:通过 getBean() 触发单例 Bean 的实例化,每个 Bean 经历:实例化 → 属性注入 → 初始化 → 生成代理(如果需要)。
  5. 销毁管理:容器关闭时,销毁单例 Bean。