Spring IoC 的价值不是“少写 new”,而是把对象的创建、依赖选择和生命周期交给一个可扩展的组装层。业务对象只声明依赖,容器根据配置创建完整对象图。
Table of contents
Open Table of contents
先运行构造器注入
打开问候服务下载。它依赖接口
GreetingPort,没有主动查找实现:
public GreetingService(GreetingPort greetingPort) {
this.greetingPort = greetingPort;
}
运行验证:
mvn -Dtest=SpringSourceLabTest#springResolvesPrimaryConstructorDependency test
**DI(依赖注入)**是 IoC 的一种实现:对象通过构造器、工厂方法或属性声明协作者,容器在创建对象时提供它们。**IoC(控制反转)**是更宽的设计原则:框架掌握流程,应用通过配置和回调参与。
五个核心角色
| 角色 | 责任 |
|---|---|
BeanDefinition | 保存 Bean 类型、作用域、构造参数等配方 |
BeanFactory | 注册配方、创建和获取 Bean |
ApplicationContext | 在 BeanFactory 上增加事件、资源、国际化等能力 |
BeanPostProcessor | 在实例初始化前后加工 Bean |
Environment | 统一访问配置属性与 Profile |
Bean 只是由容器管理的对象,不要求继承 Spring 类。BeanDefinition 是“如何创建”的元数据,单例池里的对象才是创建结果。混淆两者会看不懂启动源码。
Spring 官方说明,ApplicationContext 是 BeanFactory 的完整超集,日常应用优先使用前者。参阅IoC 容器介绍。
构造器注入为什么优先
构造器让必需依赖在对象创建时完整,字段可以保持 final,普通单元测试也能直接实例化。Setter 更适合可选依赖或确实需要重新配置的对象。字段注入隐藏依赖,降低可测试性,不适合作为默认选择。
容器带来的代价是行为变得间接:对象可能被后置处理器包装成代理,启动阶段可能提前实例化。排障时要同时检查 BeanDefinition、实际运行类型和代理链。
下一步
阅读手写最小 IoC 容器,亲手实现注册、实例化和构造器注入。