Spring依赖注入构造器与Setter

wen java案例 2

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;
    }
}

选择建议

推荐使用构造器注入的场景:

  1. 必需依赖 - 组件正常运行必须的依赖
  2. 需要不可变性 - 依赖初始化后不应改变
  3. 确保依赖完整 - 避免 NullPointerException
  4. 单元测试友好 - 测试时无需模拟容器

使用 Setter 注入的场景:

  1. 可选依赖 - 组件可以正常工作的可选组件
  2. 需要重新配置 - 运行时需要替换实现
  3. 处理循环依赖 - 特殊情况下的兼容方案
  4. 大量依赖 - 构造器参数过多时更清晰

Spring 官方推荐

Spring 官方文档明确推荐构造器注入作为主要方式:

Spring依赖注入构造器与Setter

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

抱歉,评论功能暂时关闭!