• Spring 中的 org.springframework.beans 包和 org.springframework.context 包构成了 Spring 框架 IoC 容器的基础。

  • BeanFactory 接口对 BeanFactory(是一个子接口)进行了扩展,在 BeanFactory 的基础上添加了其他功能,比如与 Spring 的 AOP 更容易集成,也提供了处理 message resource 的机制(用于国际化)、事件传播以及应用层的特别配置,比如针对 Web 应用的 WebApplicationContext。

  • org.springframework.beans.factory.BeanFactory 是 Spring IoC 容器的具体实现,用来包装和管理前面提到的各种 bean。BeanFactory 接口是 Spring IoC 容器的核心接口。

包结构与接口关系是 IoC 的”静态面”,实现面要回答三个问题:定义从哪来(BeanDefinition)、实例怎么造(反射+缓存)、依赖怎么解(注入与循环依赖)。本文按这三问把 IoC 从概念落到机制。

问题一:BeanDefinition——配置的统一中间表示

无论 XML、注解还是 Java Config,最终都被解析为 BeanDefinition:类名、scope、lazy、构造参数、property 值、init/destroy 方法等元数据的统一载体,注册进 BeanDefinitionRegistry(DefaultListableBeanFactory 内部一个 ConcurrentHashMap)。

  • 注解路径:ClassPathBeanDefinitionScanner 扫描 @Component 族 → AnnotatedBeanDefinition
  • XML 路径:BeanDefinitionDocumentReader 解析标签 → RootBeanDefinition
  • @Bean 路径:ConfigurationClassPostProcessor 解析配置类 → ConfigurationClassBeanDefinition

**IoC 的第一步是”控制配置”**:对象创建所需的全部信息被外置为数据,容器按数据造物——这就是”控制反转”中”控制”的含义(创建权从 new 转移到容器)。

问题二:实例化与缓存——getBean 的三级流水线

getBean → doGetBean 主流程:

  1. 查单例池(三级缓存体系,见下)
  2. 无则 createBean:resolveBeforeInstantiation(后处理器可提前返回代理)→ createBeanInstance(反射:构造器/工厂方法,CGLIB 用于无默认构造场景)→ populateBean(依赖注入)→ initializeBean(Aware/初始化/后处理器)
  3. 结果按 scope 处理:singleton 入池;prototype 直接返回;request/session 存入对应 Web 作用域

反射是实例化的物理手段,缓存是性能与单例语义的保证:singletonObjects 保证”一个 beanName 一个实例”。

问题三:依赖注入与循环依赖

注入发生在 populateBean:AutowiredAnnotationBeanPostProcessor 解析 @Autowired/@Value,按类型从容器找候选(多个候选再按名/优先级/qualifier 裁决),递归 getBean 完成依赖链——依赖图在容器内被递归解析,这是”依赖注入”的执行面。

循环依赖靠三级缓存(singletonObjects / earlySingletonObjects / singletonFactories):实例化后、注入前,把”能返回早期引用的工厂”放入三级;依赖方拿到早期引用完成注入,原 bean 继续填充属性。构造器循环依赖无解(实例都不存在),直接抛异常。

容器启动主线:refresh 十二步的精简版

AnnotationConfigApplicationContext 的 refresh 是 IoC 的总装线:

  1. 准备环境与事件设施
  2. 获取/创建 BeanFactory
  3. 加载 BeanDefinition(扫描/解析)
  4. 执行 BeanFactoryPostProcessor(改定义:如配置类解析、占位符替换)
  5. 注册 BeanPostProcessor(改实例:注入/AOP/代理的执行者)
  6. 初始化消息/事件/国际化设施
  7. preInstantiateSingletons:预实例化全部非懒单例(生命周期主线在此批量执行)

两类后处理器的分工是高频考点:FactoryPostProcessor 加工 BeanDefinition(还没对象),PostProcessor 加工 bean 实例(对象已建)。

IoC 带来的工程性质

  • 创建权外置 → 依赖可替换(测试注入 mock)、可配置(环境差异不改代码)
  • 依赖图显式化 → 容器可校验(缺失/循环/多义启动即报)
  • 生命周期托管 → 横切设施(AOP/事务/监控)有统一挂载点

手写最小 IoC 验证理解

class MiniContainer {
Map<String, BeanDefinition> defs = new HashMap<>();
Map<String, Object> singletons = new ConcurrentHashMap<>();

Object getBean(String name) {
return singletons.computeIfAbsent(name, n -> {
BeanDefinition d = defs.get(n);
Object obj = instantiate(d); // 反射构造
inject(obj); // 扫描字段递归 getBean 注入
return obj;
});
}
}

三十行即 IoC 内核:定义注册表 + 反射实例化 + 递归注入 + 单例缓存。Spring 的百万行代码是在这四件事上补全 scope、后处理器、循环依赖、事件等企业级边界。理解内核后读源码,refresh 的每一步都能归位到这四件事之一。