依赖 (Dependencies)
一个典型的企业级应用程序并非由单个对象(或 Spring 术语中的 Bean)组成。即使是最简单的应用程序,也有几个对象协同工作,向最终用户展示一个连贯的应用程序。接下来的部分将解释你如何从定义一系列独立的 Bean 定义,过渡到一个完整的、通过对象协作来实现目标的应用程序。
章节概览 (Section Summary)
- 依赖注入 (Dependency Injection)
- 说明构造函数注入和 Setter 注入的区别与用法。
- 依赖与配置详解 (Dependencies and Configuration in Detail)
- 深入探讨属性配置、内嵌 Bean、集合注入等细节。
- 使用 depends-on
- 控制 Bean 的初始化顺序。
- 延迟初始化的 Bean (Lazy-initialized Beans)
- 仅在首次请求时创建 Bean。
- 自动装配协作对象 (Autowiring Collaborators)
- 让容器自动解析并注入依赖。
- 方法注入 (Method Injection)
- 解决单例 Bean 注入多例 Bean 等特殊生命周期问题。
补充教学 —— 对象协作的哲学
1. 为什么要强调“依赖”? 在没有 IoC 和 DI 之前,我们常见的代码是这样的:
java
public class OrderService {
private OrderDao orderDao = new OrderDaoImpl(); // 硬编码依赖
}这种方式最大的问题是 耦合度极高。如果你想把 OrderDaoImpl 换成 OrderDaoNewImpl,或者在测试时想用一个 Mock 对象,你必须修改源码。
2. 核心概念:协作对象 (Collaborators) 在 Spring 的语境下,一个 Bean 依赖的另一个 Bean 被称为“协作对象”。
- 关系:一个对象不需要知道另一个对象是如何创建的,只需要声明“我需要它”。
- 解耦:Spring 容器就像一个中介,它负责把“提供者”和“需求者”匹配起来。
3. 进阶视角:依赖图 (Dependency Graph) 当你定义了众多的 Bean 和它们之间的引用关系时,Spring 容器内部实际上构建了一张 依赖有向图。
- 循环依赖:如果 A 依赖 B,B 也依赖 A,就会形成循环引用。Spring 有复杂的缓存机制(如三级缓存)来处理多数单例情况下的循环依赖。
- 初始化顺序:容器会确保被依赖的对象先于依赖它的对象被创建完成(除非使用了延迟初始化)。