一、常见 DI 方式
1. 构造器注入
- 利用 构造方法 的参数注入依赖。
2. Setter注入
- 调用 Setter方法 的参数注入依赖。
3. 字段注入
- 在字段上使用 @Autowired、@Resource 注解。
二、DI 方式 的优缺点
- 参考 Spring 官方文档,建议了如下的使用场景。
- 构造器注入:
强依赖性 (即必须使用此依赖),不变性 (即依赖不会经常变动)。- Setter注入:
可选 (即没有此依赖也可以运行),可变 (依赖会经常变动)。- Field注入:
多数情况尽量不使用字段注入。
一定要使用的话,@Resource 相比 @Autowired 对 IOC 容器的耦合更低。
1. Field 注入的优缺点
- 不能像 构造器注入 不可变的对象。
- 依赖对外部不可见。
外部可以看到 构造器 和 Setter方法,但无法看到 私有字段。自然无法了解 所需依赖 会导致 组件 与 IOC 容器紧耦合。
这是最重要的原因,离开了 IOC 容器去使用组件,在注入依赖时就会十分困难了。- 导致 单元测试 也必须使用 IOC 容器了。
- 依赖过多时不够明显。
比如需要 10 个依赖,用构造器注入就会显得庞大。
这时候应该考虑一下此组件是不是违反了单一职责原则。
- Field 注入 虽然有很多缺点,但它的 好处就是太方便了。
使用 构造器 或者 Setter注入 需要写更多业务无关的代码,十分麻烦,而 字段注入 大幅简化了它们。- 并且绝大多数情况下 业务代码 和 框架 就是强绑定的,完全松耦合只是一件理想上的事,牺牲了敏捷度 去过度追求 松耦合 反而得不偿失。
2. IDEA 对 @Autowired 的警告
- 使用 IDEA 开发的时候,在字段上使用 Spring 的依赖注入注解 @Autowired 后会出现如下警告:
Field injection is not recommended
(字段注入是不被推荐的)。- 但使用 @Resource 注解却不会出现此提示。
- 为什么 IDEA 只对 @Autowired 警告,却对 @Resource 视而不见呢?
- @Autowired 是 Spring 提供的,它是 特指 IOC 提供的注解,这就导致了 应用 与 框架 的强绑定,一旦换用了其他的 IOC 框架,是不能支持注入的。
- @Resource 是 JSR-250 提供的,它是 Java 标准,使用的 IOC 容器都应当去兼容它,这样即使更换容器,也可以正常工作。
3. @Autowired 和 @Resource
- 基本功能都是 通过注解实现依赖注入,只不过 @Autowired 是 Spring 定义的,而 @Resource 是 JSR-250 定义的。大致功能基本相同,有一些细节不同:
- 依赖识别方式:
@Autowired 默认是 byType,可以使用 @Qualifier 指定 Name。
@Resource 默认是 byName,如果找不到则 byType。- 适用对象:
@Autowired 可以对 构造器、方法、参数、字段使用。
@Resource 只能对方法、字段使用。- 提供方:
@Autowired 是 Spring 提供的。
@Resource 是 JSR-250 提供的。