Spring 依赖注入:构造器注入 vs Setter 注入
基本概念对比
| 特性 | 构造器注入 | Setter 注入 |
|---|---|---|
| 注入方式 | 通过构造函数参数 | 通过 setter 方法 |
| 依赖完整性 | 强制完整,必须提供所有必需依赖 | 可选,可以部分注入 |
| 不可变性 | 支持(final 字段) | 不支持 |
| 循环依赖 | 不支持 | 支持(但有风险) |
| 测试便利性 | 中等(需完整构造) | 较好(可逐步设置) |
代码示例
构造器注入
@Component
public class UserService {
private final UserRepository userRepository;
private final EmailService emailService;
// 使用 @Autowired 可省略,Spring 会自动注入
public UserService(UserRepository userRepository, EmailService emailService) {
this.userRepository = userRepository;
this.emailService = emailService;
}
// 业务方法
public void registerUser(User user) {
userRepository.save(user);
emailService.sendWelcomeEmail(user);
}
}
Setter 注入
@Component
public class UserService {
private UserRepository userRepository;
private EmailService emailService;
@Autowired
public void setUserRepository(UserRepository userRepository) {
this.userRepository = userRepository;
}
@Autowired
public void setEmailService(EmailService emailService) {
this.emailService = emailService;
}
}
选择建议
推荐使用构造器注入的场景:
- 必需依赖 - 组件正常运行必须的依赖
- 需要不可变性 - 依赖初始化后不应改变
- 确保依赖完整 - 避免 NullPointerException
- 单元测试友好 - 测试时无需模拟容器
使用 Setter 注入的场景:
- 可选依赖 - 组件可以正常工作的可选组件
- 需要重新配置 - 运行时需要替换实现
- 处理循环依赖 - 特殊情况下的兼容方案
- 大量依赖 - 构造器参数过多时更清晰
Spring 官方推荐
Spring 官方文档明确推荐构造器注入作为主要方式:

// ✅ 推荐方式
@RestController
public class UserController {
private final UserService userService;
public UserController(UserService userService) {
this.userService = userService;
}
}
// ❌ 不推荐方式
@RestController
public class UserController {
@Autowired
private UserService userService; // 字段注入(最不推荐)
}
- 首选构造器注入:保证依赖完整性和不可变性
- 可选依赖用 Setter:通过
@Autowired(required = false)标记 - 避免字段注入:不利于测试和调试
- 单一职责:如果构造器参数过多,考虑重构类
- 使用 @RequiredArgsConstructor:Lombok 简化代码
// Lombok 简化构造器注入
@RequiredArgsConstructor
@Service
public class OrderService {
private final OrderRepository orderRepository;
private final PaymentService paymentService;
private final NotificationService notificationService;
// 自动生成包含所有 final 字段的构造器
}