Spring 依赖注入

一、三大基础注入方式

1. 构造器注入(官方推荐首选)

复制代码
@Service
public class XxxService {
    private final XxxDao xxxDao;
    // 强制注入,依赖不可为空
    public XxxService(XxxDao xxxDao) {
        this.xxxDao = xxxDao;
    }
}
  • 优点:支持final、强制依赖、减少空指针、缓解循环依赖
  • 适用:项目核心必选依赖

2. Setter 设值注入

复制代码
@Service
public class XxxService {
    private XxxDao xxxDao;
    @Autowired
    public void setXxxDao(XxxDao xxxDao) {
        this.xxxDao = xxxDao;
    }
}
  • 优点:灵活,容器初始化后可动态修改依赖
  • 适用:非必需、可选依赖

3. 字段注入(不推荐生产使用)

复制代码
@Service
public class XxxService {
    @Autowired
    private XxxDao xxxDao;
}
  • 缺点:不能用 final、隐藏依赖、脱离 Spring 难以单元测试、更容易循环依赖

二、配套注入注解

1. @Autowired(Spring 原生,核心注入注解)

  • 默认按类型匹配 Bean;
  • 多个同类型 Bean 会报NoUniqueBeanDefinitionException歧义异常;
  • 可作用于构造、set 方法、成员变量。

2. @Qualifier(@Autowired 配套限定注解,非独立注入方式)

作用:同接口多实现时,指定 Bean 名称精准匹配,解决注入冲突。 使用位置:构造参数、set 参数、成员变量上方

复制代码
// 多实现场景
@Autowired
@Qualifier("mysqlUserDao")
private UserDao userDao;

3. @Primary(@Qualifier 替代方案)

在其中一个实现类添加,Spring 自动优先注入该 Bean,只能设置一个主 Bean,灵活性差。

复制代码
@Repository
@Primary
public class MysqlUserDao implements UserDao {}

4. @Resource(JSR-250 规范)

  • 优先按 Bean 名称匹配,无需搭配@Qualifier

  • 不支持构造方法注入。

    @Resource(name = "mysqlUserDao")
    private UserDao userDao;

5. @Inject(JSR-330 规范)

功能近似@Autowired,无required属性,需额外引入依赖,项目极少使用。

6. @Value(普通值注入)

注入字面量、配置文件属性(简单类型,非对象 Bean 注入)

复制代码
@Value("${server.port}")
private Integer port;

三、集合批量注入

同类型所有 Bean 可直接注入到集合 / 数组,无需@Qualifier

复制代码
@Autowired
private List<UserDao> daoList;

四、三种注入方式对比

注入方式 优点 缺点 推荐度
构造器注入 依赖不可为空、线程安全、易测试、循环依赖少 可选依赖需重载构造 ⭐⭐⭐⭐⭐ 生产首选
Setter 注入 可动态修改依赖,适配可选依赖 实例创建后赋值,存在空指针风险 ⭐⭐⭐ 仅可选依赖使用
字段注入 代码简洁、书写少 无法 final、难单元测试、隐藏依赖 ⭐ 不推荐

五、总结

  • 注入方式只有三类:构造注入、set 注入、字段注入;
  • @Autowired/@Resource/@Inject实现注入的注解
  • @Qualifier/@Primary辅助限定注解,用来解决多 Bean 冲突,不属于注入方式;
  • @Value专门注入普通配置值,不用于对象 Bean 依赖注入。
相关推荐
swipe11 分钟前
11|(前端转全栈)购物车不能只存在前端:用户维度数据如何在后端落库
前端·后端·全栈
薛定谔的猫-菜鸟程序员11 分钟前
基于 Electron 的本地短视频解析与下载工具:架构设计与工程实践
java·electron·音视频
音符犹如代码1 小时前
Arthas Profiler 火焰图实战:CPU 热点在哪一目了然
java·jvm·spring boot
小园子的小菜1 小时前
Java 并发编程:线程安全队列全解 —— 阻塞与非阻塞实现原理及源码深度剖析
java·开发语言
好好沉淀1 小时前
Windows 下升级 Maven 3.6.1 到 3.9.9 踩坑全记录
java·windows·maven
CodexDave1 小时前
Python 自动化接单实战(一):把 CSV 需求做成配置驱动解析器
java·python·自动化·json·数据清洗·python自动化·csv处理
XS0301062 小时前
Spring框架
java·后端·spring
Rabitebla2 小时前
C++ 内存管理全面复习:从内存分布到 operator new/delete
java·c语言·开发语言·c++·算法·leetcode
xcLeigh2 小时前
Go入门:main包与main函数的特殊地位
开发语言·后端·golang
萧瑟余晖2 小时前
Java深入解析篇四之函数式编程详解
java·开发语言