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。
相关推荐
程序员黑豆20 小时前
AI全栈开发之Java:什么是JDK
前端·后端·ai编程
阿明在折腾21 小时前
从Canvas到AI模型:我在线工具站里的图片处理实战
前端·后端
tyung21 小时前
Go 手写 Wait-Free SPSC 无界队列:无 CAS、无锁、泛型节点池
数据结构·后端·go
Lucien32321 小时前
学完 Spring Boot 再看 FastAPI,我破防了
后端
小小龙学IT21 小时前
Go 语言后端开发:从并发模型到生产落地的工程实践
开发语言·后端·golang
程序员cxuan21 小时前
Agents.md 是什么
人工智能·后端·程序员
摇滚侠21 小时前
Java 零基础全套教程,类的加载过程与类加载器的理解,笔记 189
java·后端·intellij-idea
ServBay21 小时前
为什么我劝你不要在Mac上用Docker 进行本地 AI 开发
后端
蝎子莱莱爱打怪21 小时前
XZLL-IM干货系列 02|Protobuf 协议设计:从 JSON 切到二进制,每条消息省了 60%
后端·面试·架构
程序员黑豆1 天前
AI全栈开发之Java:第一个Java程序
前端·后端·ai编程