Spring源码又看了一遍

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


一、容器启动入口

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

java

ini 复制代码
ApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);

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

java

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

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

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

java

scss 复制代码
@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

scss 复制代码
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> 标签。
  • 通过 BeanPostProcessorpostProcessAfterInstantiation 钩子,允许修改属性注入前状态。

3.4 initializeBean()

  • 依次执行:

    1. 调用 Aware 方法(如 BeanNameAwareBeanFactoryAwareApplicationContextAware 等)。
    2. 执行 BeanPostProcessorpostProcessBeforeInitialization(如 @PostConstruct 在此阶段被调用)。
    3. 执行自定义 init-methodInitializingBean.afterPropertiesSet()
    4. 执行 BeanPostProcessorpostProcessAfterInitialization(AOP 代理在此生成,如 AnnotationAwareAspectJAutoProxyCreator)。

9. finishRefresh()

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

四、关键源码位置速查

步骤 关键类 关键方法
容器刷新 AbstractApplicationContext refresh()
BeanDefinition 注册 ConfigurationClassPostProcessor postProcessBeanDefinitionRegistry()
Bean 实例化 AbstractAutowireCapableBeanFactory doCreateBean()
依赖注入 AbstractAutowireCapableBeanFactory populateBean()
循环依赖解决 DefaultSingletonBeanRegistry getSingleton()、三级缓存
初始化回调 AbstractAutowireCapableBeanFactory initializeBean()
AOP 代理生成 AbstractAutoProxyCreator postProcessAfterInitialization()

五、总结

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

  1. 配置加载 :通过 BeanDefinitionReader 读取配置,生成 BeanDefinition 并注册。
  2. 后处理器调用 :执行 BeanFactoryPostProcessorBeanDefinition 进行修改(如占位符替换、配置类解析)。
  3. 注册后处理器 :注册 BeanPostProcessor,为 Bean 创建做好准备。
  4. Bean 创建 :通过 getBean() 触发单例 Bean 的实例化,每个 Bean 经历:实例化 → 属性注入 → 初始化 → 生成代理(如果需要)。
  5. 销毁管理:容器关闭时,销毁单例 Bean。
相关推荐
希望永不加班2 小时前
SpringBoot 主启动类解释:@SpringBootApplication 到底做了什么
java·spring boot·后端·spring
一只叫煤球的猫2 小时前
为什么不用 RAG 做记忆系统 ——压缩上下文与 memory.md 的架构选择
人工智能·后端·ai编程
智能工业品检测-奇妙智能2 小时前
国产化系统的性价比对比
人工智能·spring boot·后端·openclaw·奇妙智能
编码忘我2 小时前
java强引用、软引用、弱引用、虚引用
后端
蝎子莱莱爱打怪3 小时前
别再裸用 Claude Code 了!32 个亲测Skills + 8 个 MCP,开发效率直接拉满!
java·后端·claude
犯困的饭团3 小时前
4_【自动化引擎Ansible Runner】将 Runner 嵌入灵魂 - Python API 编程
后端
AI茶水间管理员3 小时前
爆火的OpenClaw到底强在哪?一文了解核心架构(附一条消息的全链路流程)
人工智能·后端
Java水解3 小时前
Rust异步缓存系统的设计与实现
后端·rust
野犬寒鸦3 小时前
JVM垃圾回收机制面试常问问题及详解
java·服务器·开发语言·jvm·后端·算法·面试