当前位置: 首页 > news >正文

依赖注入是什么?什么时候要用到依赖注入?为什么相较于使用@Resource或者@Autowired,spring官方更推荐使用构造函数进行依赖注入?

依赖注入(Dependency Injection,DI)是一种设计模式,用于解耦组件之间的依赖关系,通过外部(如框架)将依赖项“注入”到对象中,而不是由对象自行创建或查找依赖。它的核心目标是实现控制反转(IoC),提升代码的灵活性、可测试性和可维护性。


一、依赖注入是什么?

  1. 基本概念

    • 依赖:一个对象需要其他对象才能完成功能(例如:UserService 需要 UserRepository)。

    • 注入:由外部(如 Spring 容器)主动将依赖对象传递给目标对象,而不是目标对象自己创建依赖。

  2. 实现方式

    • 构造函数注入:通过构造函数参数传递依赖。

    • Setter 方法注入:通过 setter 方法设置依赖。

    • 字段注入:通过 @Autowired 或 @Resource 直接注入字段(不推荐)。


二、什么时候要用到依赖注入?

  1. 解耦组件
    当一个类需要依赖其他服务(如数据库访问、外部 API)时,通过 DI 将依赖的创建和管理交给框架,避免硬编码依赖。

  2. 提升可测试性
    依赖注入允许在单元测试中轻松替换依赖的模拟对象(Mock)。例如:

    java

    复制

    // 生产环境注入真实的 UserRepository
    UserService userService = new UserService(realUserRepo);
    
    // 测试环境注入 Mock 的 UserRepository
    UserService userService = new UserService(mockUserRepo);
  3. 管理复杂依赖关系
    Spring 容器可以自动处理依赖的创建、生命周期和依赖之间的关联(如循环依赖)。


三、为什么 Spring 官方推荐构造函数注入?

相较于 @Autowired(字段注入)或 @Resource构造函数注入是 Spring 官方推荐的方式,原因如下:

1. 保证依赖不可变(Immutability)
  • 字段注入的依赖可以被修改(非 final),而构造函数注入允许将字段声明为 final,确保依赖在对象创建后不可变。

java

复制

// 构造函数注入(依赖不可变)
public class UserService {
    private final UserRepository userRepo;
    
    public UserService(UserRepository userRepo) {
        this.userRepo = userRepo;  // final 字段必须在构造函数中初始化
    }
}
2. 避免空指针异常(NPE)
  • 构造函数注入强制在对象创建时完成所有必需依赖的初始化,确保依赖不为 null

  • 字段注入或 Setter 注入可能导致依赖未被正确注入,后续使用时报 NPE

3. 明确依赖的必要性
  • 构造函数参数清晰地表明了一个类的必需依赖,而 Setter 注入或字段注入可能让依赖看起来是“可选”的。

4. 兼容不可变性框架
  • 如 Java 的 Records、Kotlin 的 data class 等不可变数据结构,必须通过构造函数注入依赖。

5. 更好的代码静态分析
  • IDE 和静态分析工具(如 Sonar)可以通过构造函数参数直接识别依赖关系,而字段注入需要扫描注解。

6. 避免循环依赖问题
  • 构造函数注入在 Spring 中会显式暴露循环依赖(启动时报错),而字段注入可能隐式掩盖问题,导致运行时异常。


四、代码示例对比

字段注入(不推荐)

java

复制

public class UserService {
    @Autowired  // 依赖可能未被注入,导致后续 userRepo 为 null
    private UserRepository userRepo;
}
构造函数注入(推荐)

java

复制

public class UserService {
    private final UserRepository userRepo;
    
    // Spring 4.3+ 自动识别唯一构造函数,无需 @Autowired
    public UserService(UserRepository userRepo) {
        this.userRepo = userRepo;  // 强制初始化,避免 NPE
    }
}

五、总结

  • 依赖注入的核心价值是解耦可测试性

  • 构造函数注入是 Spring 官方推荐的方式,因为它:

    1. 强制依赖不可变,确保对象状态安全;

    2. 避免空指针异常;

    3. 明确依赖的必要性;

    4. 兼容现代编程范式(如不可变对象)。

除非依赖是可选的(如配置参数),否则应优先使用构造函数注入。

相关文章:

  • Day02-云服务器+小皮phpstudy一键部署建站
  • Pytorch实现之LSRGAN,轻量化SRGAN超分辨率SAR
  • setlocale()的参数,“zh_CN.UTF-8“, “chs“, “chinese-simplified“的差异。
  • postgresql
  • GaussDB自带诊断工具实战指南
  • 青训营:简易分布式爬虫
  • 【Spring Boot 应用开发】-04-02 自动配置-数据源-手撸一个最简持久层工具类
  • 【CF记录】贪心——A. Scrambled Scrabble
  • 计算机毕业设计SpringBoot+Vue.js教师工作量管理系统(源码+文档+PPT+讲解)
  • PHP之变量
  • 前端模拟数据调试的方法
  • io学习----->文件io
  • 什么是索引下推?
  • 机器视觉开发教程——封装Halcon通用模板匹配工具【含免费教程源码】
  • java 查找两个集合的交集部分数据
  • K8s 1.27.1 实战系列(一)准备工作
  • 【零基础到精通Java合集】第二十九集:SQL常用优化手段
  • 双链路提升网络传输的可靠性扩展可用带宽
  • 【Oracle学习笔记】1.数据库组成对象
  • 前端开发10大框架深度解析
  • 工行回应两售出金条疑似有杂质:情况不属实,疑似杂质应为金条售出后的外部附着物
  • 2025中国南昌国际龙舟赛5月23日启幕,是历年来南昌举办的最高规格龙舟赛事
  • 上海国际电影节推出三大官方推荐单元,精选十部优秀影片
  • 欧洲承诺投资6亿欧元吸引外国科学家
  • 印度杰纳布河上游两座水电站均已重新开闸
  • 经济日报:落实落细更加积极的财政政策