IoC/DI 思想与容器职责

结论先行:IoC(控制反转)是把"对象创建 + 依赖装配"的控制权从代码自身反转到容器;DI(依赖注入)是容器实现 IoC 的主要手段——容器创建 Bean 时把它的依赖"注入"进来,调用方只声明依赖、不负责 new。Spring IoC 容器(BeanFactory/ApplicationContext)的职责可归纳为一条流水线:解析 Bean 定义 → 实例化 → 依赖注入 → 生命周期管理 →(按需)AOP 代理织入与事件发布。

一、IoC 与 DI 的关系

  • IoC 是思想/原则:谁控制谁——原来对象自己 new 依赖(正转),现在容器统一创建并组装(反转);
  • DI 是落地方式:容器通过构造器、setter 或字段把依赖传给对象;
  • 反过来控制反转还有其他形式(如 Service Locator),但 Spring 主推 DI,面试时先说"Spring 的 IoC 通过 DI 实现"。

二、三种注入方式对比

方式写法优点缺点
构造器注入构造器参数接收依赖不可变(final)、易测试、必填依赖显式依赖多时代码长;构造器循环依赖不可解
Setter 注入setter 方法可选依赖、可后期重配依赖可变、可能遗漏注入
字段注入@Autowired 直接标字段代码最简隐藏依赖、难单测、与容器强耦合
  • 官方推荐:构造器注入(Spring 团队文档明确建议);Boot 中也最常见;
  • 字段注入在面试中常被问"为什么不推荐":依赖关系不可见、无法脱离容器做单元测试。

三、容器职责链

  1. 读取配置/扫描注解,解析出 BeanDefinition(bean 的类型、作用域、依赖、初始化方法等);
  2. 按需实例化对象(默认单例并预实例化,见 03);
  3. 依赖注入(populateBean,@Autowired/@Value 在此阶段生效);
  4. 生命周期管理:Aware 回调、初始化、销毁回调(见 04);
  5. 扩展能力:BeanPostProcessor 链(AOP 代理在此产生)、事件发布。
@Service
public class OrderService {
    private final PaymentGateway gateway;   // 只声明依赖,不 new

    public OrderService(PaymentGateway gateway) {   // 构造器注入:容器负责传参
        this.gateway = gateway;
    }
}

常见追问 / 记忆点

  • 追问:IoC 容器里 Bean 什么时候被创建?答:默认单例 Bean 在 ApplicationContext 启动刷新时预实例化(eager),prototype 与懒加载 Bean 在首次 getBean/被注入时创建。
  • 追问:IoC 最大的好处?答:解耦(替换实现只改配置/注解)、便于单元测试(可注入 Mock)、对象统一管理。
  • 记忆点:"反转的是创建权,注入的是依赖,容器是总装配车间"。
笔记加载中…