IoC 容器解决的问题
Spring IoC 容器负责根据配置创建对象、连接依赖并管理生命周期。业务对象只声明自己需要什么,不再负责查找依赖或决定依赖的具体实现。
1. 对象内部创建依赖会固定实现
public final class OrderService {
private final PaymentClient paymentClient =
new HttpPaymentClient("https://pay.example.com");
}
OrderService 同时决定业务流程、客户端实现和地址。测试时难以替换为本地桩,生产配置变化也需要修改业务代码。
将依赖交给构造器后,对象只保留协作关系:
public final class OrderService {
private final PaymentClient paymentClient;
public OrderService(PaymentClient paymentClient) {
this.paymentClient = paymentClient;
}
}
谁创建 PaymentClient、选择哪个实现,由应用装配边界决定。
2. IoC 与 DI 描述不同层次
**控制反转(IoC)**指对象创建和协作关系的控制权从业务对象转移到外部容器。**依赖注入(DI)**是实现方式:容器通过构造器、工厂方法或属性把依赖交给对象。
Spring 容器还负责:
- 从 Java 配置、组件扫描或其他来源读取对象定义。
- 解析按类型、名称、限定符表达的依赖关系。
- 执行初始化、销毁和作用域协议。
- 应用事务、异步、校验等基础设施处理器。
3. 容器管理的是 BeanDefinition 与实例
容器先注册 BeanDefinition,其中描述类、工厂方法、作用域、依赖、初始化方式等元数据;需要对象时,再按照定义创建 Bean。
@Configuration
class PaymentConfiguration {
@Bean
PaymentClient paymentClient(PaymentProperties properties) {
return new HttpPaymentClient(properties.endpoint());
}
}
@Bean 方法的参数也是依赖声明。容器解析 PaymentProperties,再调用工厂方法得到实例。
4. 依赖集中以后更容易替换与观察
测试可以直接构造业务对象:
PaymentClient stub = request -> PaymentResult.approved();
OrderService service = new OrderService(stub);
不需要为每个单元测试启动 Spring。集成测试再验证扫描、条件配置、代理和数据库等容器行为。
容器还能统一记录 Bean 创建时间、依赖图和配置来源,但集中管理也使启动链路更长。出现重复 Bean、条件不匹配或循环依赖时,需要查看容器证据,而不是只沿着 new 调用查找。
5. 容器边界应保持在应用装配层
业务类频繁调用 applicationContext.getBean(...) 会重新变成 Service Locator:依赖从构造器签名中消失,测试和静态分析都更困难。
动态选择可以使用注入的 Map<String, Strategy>、ObjectProvider<T> 或明确的工厂接口。只有框架扩展、插件系统等确实需要查询容器时,才直接使用容器 API。
6. 常见问题
6.1 使用 Spring 以后还可以 new 对象吗
当然可以。实体、值对象和方法内部短生命周期对象通常直接创建。需要容器注入、代理、作用域或生命周期管理的组件才应成为 Bean。
6.2 IoC 能消除对象之间的耦合吗
不能。OrderService 仍然依赖 PaymentClient 的契约。IoC 让实现选择和构建过程从业务逻辑中分离,使耦合更明确、更容易替换。
7. 面试题
7.1 Spring IoC 和依赖注入分别是什么
出现公司:美团
考察重点
- 对象控制权与依赖提供方式。
- BeanDefinition、实例和生命周期。
- 容器不能消除业务契约。
相关内容:第 1 节“对象内部创建依赖会固定实现”至第 3 节“容器管理的是 BeanDefinition 与实例”。
参考回答
IoC 是把对象创建、实现选择和生命周期交给外部容器;DI 是容器通过构造器、工厂方法或属性把协作对象交给 Bean。业务对象因此只声明依赖,不负责查找或创建具体实现。
Spring 先把配置表示成 BeanDefinition,再按作用域创建实例、解析依赖并执行扩展点。它让装配更容易替换和测试,但依赖契约仍然存在,也会增加容器启动和诊断成本。