Spring IOC 核心源码解析

Spring IOC 核心源码解析

一、核心入口

对于新手来说,不用一上来就啃全量源码,先抓住核心入口类核心流程 :本文以 Spring 6.x 中基于注解的 IOC 容器入口是 AnnotationConfigApplicationContext,创建容器的核心代码:

ini 复制代码
// 最简容器初始化代码
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
NotificationController controller = context.getBean(NotificationController.class);

这一行代码背后,就是 IOC 容器的完整生命周期,我们拆解为 4 个核心步骤:

二、IOC 核心流程源码拆解

步骤 1:容器初始化 - 刷新上下文(核心方法:refresh ())

AnnotationConfigApplicationContext 构造方法最终会调用 AbstractApplicationContextrefresh() 方法,这是 IOC 容器的 "总开关",核心代码简化如下:

scss 复制代码
@Override
public void refresh() throws BeansException, IllegalStateException {
    synchronized (this.startupShutdownMonitor) {
        // 1. 准备刷新:初始化环境、校验配置
        prepareRefresh();

        // 2. 获取 BeanFactory(核心容器),加载 Bean 定义
        ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

        // 3. 准备 BeanFactory:设置类加载器、注册内置 Bean 等
        prepareBeanFactory(beanFactory);

        try {
            // 4. 后置处理 BeanFactory(扩展点)
            postProcessBeanFactory(beanFactory);

            // 5. 执行 BeanFactory 后置处理器(扫描并注册 BeanDefinition)
            invokeBeanFactoryPostProcessors(beanFactory);

            // 6. 注册 Bean 后置处理器(处理注解如@Autowired、@PostConstruct)
            registerBeanPostProcessors(beanFactory);

            // 7. 初始化消息源(国际化)
            initMessageSource();

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

            // 9. 子类扩展:初始化其他 Bean(如 Web 环境的 ThemeSource)
            onRefresh();

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

            // 11. 实例化所有非懒加载的单例 Bean(核心!)
            finishBeanFactoryInitialization(beanFactory);

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

重点关注:步骤 5(扫描 Bean)和步骤 11(实例化 Bean)是 IOC 的核心中的核心。

步骤 2:扫描 Bean - 生成 BeanDefinition

步骤 5 中,ConfigurationClassPostProcessor 会扫描指定包下的注解类(@Component、@Service、@Controller 等),将每个类封装为 BeanDefinition(Bean 定义元信息,包含类名、作用域、依赖等),并存入 BeanFactorybeanDefinitionMap 中。核心逻辑在 ClassPathBeanDefinitionScannerdoScan() 方法:

ini 复制代码
protected Set<BeanDefinitionHolder> doScan(String... basePackages) {
    Set<BeanDefinitionHolder> beanDefinitions = new LinkedHashSet<>();
    for (String basePackage : basePackages) {
        // 扫描包下的类,生成 BeanDefinition
        Set<BeanDefinition> candidates = findCandidateComponents(basePackage);
        for (BeanDefinition candidate : candidates) {
            // 设置作用域(默认单例)
            ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(candidate);
            candidate.setScope(scopeMetadata.getScopeName());
            // 生成 Bean 名称(默认类名首字母小写)
            String beanName = this.beanNameGenerator.generateBeanName(candidate, this.registry);
            // 处理通用注解(如@Lazy、@Primary)
            AnnotationConfigUtils.processCommonDefinitionAnnotations(candidate);
            // 注册 BeanDefinition 到容器
            if (checkCandidate(beanName, candidate)) {
                BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(candidate, beanName);
                definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
                beanDefinitions.add(definitionHolder);
                registerBeanDefinition(definitionHolder, this.registry);
            }
        }
    }
    return beanDefinitions;
}

核心概念BeanDefinition 是 Spring 对 Bean 的 "描述",容器先存描述,再根据描述创建实例,这是 Spring 灵活扩展的关键。

步骤 3:实例化 Bean - createBean ()

步骤 11 中,DefaultListableBeanFactorypreInstantiateSingletons() 方法会遍历所有 BeanDefinition,调用 createBean() 方法创建实例,核心流程:

  1. 创建 Bean 实例 :通过反射调用构造方法(instantiateBean());
  2. 依赖注入 :处理 @Autowired 注解,从容器中获取依赖 Bean 并注入(populateBean());
  3. 初始化 Bean :执行 @PostConstruct 注解方法、初始化方法(initializeBean());
  4. 存入容器 :将创建好的单例 Bean 存入 singletonObjects(单例池)。

核心代码简化:

less 复制代码
protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) throws BeanCreationException {
    try {
        // 1. 创建 Bean 实例
        Object beanInstance = doCreateBean(beanName, mbd, args);
        // 2. 依赖注入 + 初始化
        populateBean(beanName, mbd, beanInstance);
        exposedObject = initializeBean(beanName, exposedObject, mbd);
        return exposedObject;
    } catch (BeansException ex) {
        destroyBean(beanName, mbd, beanInstance);
        throw ex;
    }
}

步骤 4:依赖注入 - AutowiredAnnotationBeanPostProcessor

@Autowired 注解的处理核心是 AutowiredAnnotationBeanPostProcessor,它是一个 BeanPostProcessor(Bean 后置处理器),在 populateBean() 阶段执行:

  • 扫描 Bean 的字段 / 方法上的 @Autowired 注解;
  • 根据类型 / 名称从容器中查找依赖的 Bean;
  • 通过反射注入依赖(支持字段注入、构造器注入、setter 注入)。

三、看源码的建议

  1. 先跑通最简案例 :写一个只有 AppConfig + NotificationController 的最简项目,debug 跟踪 AnnotationConfigApplicationContext 的创建流程;
  2. 抓核心不贪全:先搞懂「扫描→BeanDefinition→实例化→注入」4 个核心步骤,再看扩展点(后置处理器、生命周期);

📌 关注我 ,每天5分钟,带你从 Java 小白变身编程高手!

👉 点赞 + 关注,让更多小伙伴一起进步!

相关推荐
hongtianzai3 分钟前
Laravel8.x核心特性全解析
java·c语言·开发语言·golang·php
逸Y 仙X6 分钟前
文章十一:ElasticSearch Dynamic Template详解
java·大数据·数据库·elasticsearch·搜索引擎·全文检索
隔壁小邓8 分钟前
IDEA 中同时启动多个微服务
java·微服务·intellij-idea
:1218 分钟前
idea17创建tomcat项目(计网底层核心理解!)
java·ide·intellij-idea
Brookty12 分钟前
网络通信核心:四元组、socket与IO机制详解
java·网络通信·网络入门
佩奇大王22 分钟前
P159 摆动序列
java·开发语言·算法
计算机学姐24 分钟前
基于SpringBoot的网吧管理系统
java·spring boot·后端·spring·tomcat·intellij-idea·mybatis
Boop_wu26 分钟前
[Java EE 进阶] SpringBoot 配置文件全解析:properties 与 yml 的使用(1)
java·spring boot·spring·java-ee
我不是秋秋27 分钟前
软件开发项目各角色关系解析:产品/前后端/测试如何高效协作?
java·算法·面试·职场和发展·哈希算法
青衫客3629 分钟前
浅谈 Java 后端对象映射:从 JSON → VO → Entity 的原理与实践
java·json