题目
Spring框架中依赖注入的两种主要方式及其区别
信息
- 类型:问答
- 难度:⭐
考点
依赖注入方式,构造函数注入,Setter注入,Spring基础
快速回答
Spring框架实现依赖注入的两种主要方式是:
- 构造函数注入:通过类的构造函数传递依赖
- Setter注入:通过setter方法传递依赖
主要区别:
- 构造函数注入强制依赖项在对象创建时初始化,适合必需依赖
- Setter注入提供更灵活的依赖设置,适合可选依赖
1. 原理说明
依赖注入(DI)是Spring框架实现控制反转(IoC)的核心技术,将对象依赖关系的创建从代码内部转移到外部容器管理。两种主要实现方式:
- 构造函数注入:容器通过调用类的构造函数传递依赖对象,强制在对象实例化时完成依赖注入
- Setter注入:容器调用类的setter方法注入依赖,可在对象创建后灵活设置
2. 代码示例
示例类定义
// 服务类
public class EmailService {
public void sendEmail(String message) {
System.out.println("发送邮件: " + message);
}
}
// 使用依赖的类
public class UserService {
private final EmailService emailService;
// 构造函数注入
public UserService(EmailService emailService) {
this.emailService = emailService;
}
// Setter注入
private SmsService smsService;
public void setSmsService(SmsService smsService) {
this.smsService = smsService;
}
public void notifyUser() {
emailService.sendEmail("欢迎注册");
}
}XML配置示例
<!-- 构造函数注入 -->
<bean id="userService" class="com.example.UserService">
<constructor-arg ref="emailService"/>
</bean>
<!-- Setter注入 -->
<bean id="userService" class="com.example.UserService">
<property name="smsService" ref="smsService"/>
</bean>注解配置示例
@Service
public class UserService {
// 构造函数注入(推荐)
private final EmailService emailService;
@Autowired
public UserService(EmailService emailService) {
this.emailService = emailService;
}
// Setter注入
private SmsService smsService;
@Autowired
public void setSmsService(SmsService smsService) {
this.smsService = smsService;
}
}3. 核心区别对比
| 特性 | 构造函数注入 | Setter注入 |
|---|---|---|
| 依赖必要性 | 强制要求依赖(适合必需依赖) | 可选依赖(适合非必需依赖) |
| 注入时机 | 对象创建时立即注入 | 对象创建后可延迟注入 |
| 不变性 | 支持final字段(线程安全) | 字段通常可变 |
| 循环依赖 | Spring无法解决构造器循环依赖 | 能解决setter循环依赖 |
4. 最佳实践
- 优先使用构造函数注入强制依赖项(Spring官方推荐)
- 使用Setter注入处理可选依赖或需要重新配置的场景
- 在Spring 4.3+版本中,单个构造函数的类可省略@Autowired注解
- 对必需依赖使用final字段保证不可变性和线程安全
5. 常见错误
- 循环依赖问题:两个类相互通过构造函数注入会导致Bean创建失败
错误示例:ClassA → 构造函数依赖ClassB → 构造函数依赖ClassA - 混合使用时不恰当的null检查:Setter注入的依赖需做null判断
- 在构造函数中调用依赖方法:此时依赖可能尚未完全初始化
6. 扩展知识
- 字段注入(@Autowired直接加在字段上):虽然方便但不被推荐(隐藏依赖、难测试、破坏封装性)
- JavaConfig配置方式:使用@Bean方法显式配置依赖关系
- Qualifier注解:当存在多个同类型Bean时指定具体注入对象
- Spring 5推荐的函数式配置:通过GenericApplicationContext注册Bean