尧图网站建设 尧图网络
  • 首页
  • 关于我们
  • 服务项目
  • 案例展示
  • 建站流程
  • 资讯中心
  • 联系我们
首页/资讯中心/详情

Spring三大注入注解深度拆解:@Autowired、@Resource、@RequiredArgsConstructor 原理、示例、场景选型、面试全解

Spring三大注入注解深度拆解:@Autowired、@Resource、@RequiredArgsConstructor 原理、示例、场景选型、面试全解
📅 发布时间:2026/6/26 19:52:08

Spring三大注入注解深度拆解:@Autowired、@Resource、@RequiredArgsConstructor 原理、示例、场景选型、面试全解

前言

做 Spring 开发,依赖注入 DI是每日必写代码,90% 开发者都会混淆三个高频注解:@Autowired、@Resource、@RequiredArgsConstructor。
很多人只会机械复制代码,分不清三者出身、匹配规则、优缺点,面试连环追问直接卡壳;项目混用多种注入方式,代码规范混乱、循环依赖、空指针、多实现 Bean 启动报错层出不穷。

本文一次性讲透:三者底层原理、完整可运行示例、相同点、核心差异、分场景选型规范、高频踩坑、面试标准答案,适合收藏作为团队代码规范参考。

一、基础总览:一句话分清三者定位

注解所属来源核心本质核心作用
@AutowiredSpring 框架专属注入标记注解标记字段 / 构造 /setter,Spring 自动装配 Bean,默认按类型匹配
@ResourceJSR-250 Java 官方标准注入标记注解Java 规范注解,跨容器兼容,优先按 Bean 名称匹配
@RequiredArgsConstructorLombok 工具类代码生成语法糖编译期自动生成 final/@NonNull 字段构造,本身不具备注入能力,配合 Spring 构造注入简化代码

核心共识:三者最终目标统一 —— 交给 Spring IoC 容器管理依赖,无需手动 new 对象,解耦业务代码。

二、逐个详解:源码示例、底层规则、使用场景

2.1 @Autowired(Spring 原生注入注解)

1)依赖包
importorg.springframework.beans.factory.annotation.Autowired;
2)底层匹配规则
  1. 默认byType(按类类型)优先匹配容器 Bean;

  2. 同接口多个实现类时报错,搭配@Qualifier("beanName")指定名称区分;

  3. 支持required = true/false:

    • required=true(默认):找不到 Bean 直接抛异常,项目启动失败;

    • required=false:找不到依赖不报错,字段为 null;

  4. 可标注位置:字段、构造方法、setter 方法、普通业务方法、方法参数。

3)完整可运行三种写法示例
① 字段注入(简单但 Spring 不推荐生产)
@ServicepublicclassUserService{// 直接标注字段,Spring自动注入UserMapper@AutowiredprivateUserMapperuserMapper;publicUsergetById(Longid){returnuserMapper.selectById(id);}}

缺点:字段无法加final,对象可被二次修改;单元测试需要反射赋值,无法提前暴露循环依赖。

② 构造方法注入(Spring 官方第一推荐)

Spring4.3 特性:类只有一个构造器时,可省略@Autowired自动注入

@ServicepublicclassUserService{// final修饰,对象不可变,杜绝空指针privatefinalUserMapperuserMapper;privatefinalRedisTemplate<String,Object>redisTemplate;// 构造注入,依赖在对象创建时全部就绪@AutowiredpublicUserService(UserMapperuserMapper,RedisTemplate<String,Object>redisTemplate){this.userMapper=userMapper;this.redisTemplate=redisTemplate;}}
③ Setter 注入(仅适合可选依赖)
@ServicepublicclassUserService{privateLogClientlogClient;// 日志客户端非必选组件,找不到不影响项目启动@Autowired(required=false)publicvoidsetLogClient(LogClientlogClient){this.logClient=logClient;}}
④ 解决多实现类冲突:搭配 @Qualifier
// 支付接口,两个实现类:AliPay、WechatPaypublicinterfacePayHandler{}@Component("aliPay")publicclassAliPayimplementsPayHandler{}@Component("wechatPay")publicclassWechatPayimplementsPayHandler{}// 使用@Autowired + @Qualifier指定Bean名称@ServicepublicclassOrderService{@Autowired@Qualifier("aliPay")privatePayHandlerpayHandler;}
4)适用场景
  1. 需要可选依赖(required=false),组件不存在不阻塞项目启动;

  2. 多实现接口场景,灵活搭配@Qualifier精准指定 Bean;

  3. 需要注入 Spring 底层原生组件(RestTemplate、TransactionManager 等);

  4. 项目禁止引入 Lombok,只能手写构造注入;

  5. 需要 setter 延迟注入、动态替换依赖的场景。

5)缺点
  • 字段注入无法使用final,线程安全性弱;

  • 纯字段注入隐藏依赖关系,代码可读性差;

  • 大量依赖时手写超长构造,代码冗余。

2.2 @Resource(JSR-250 Java 标准注解)

1)依赖包(JDK 内置,无需额外引入)
importjavax.annotation.Resource;
2)底层匹配规则
  1. 优先 byName(按名称匹配),找不到同名 Bean 再降级 byType 按类型匹配;

  2. 支持name属性手动指定 Bean 名称:@Resource(name = "xxx");

  3. 无required参数,依赖缺失直接启动报错,不支持可选注入;

  4. 限制:不能标注在构造方法上,仅支持字段、setter 方法;

  5. 框架无关:不绑定 Spring,兼容 Jakarta EE、JBoss 等其他 IoC 容器。

3)完整代码示例
① 不指定 name:优先匹配和字段同名 Bean
@ServicepublicclassUserService{// 先找容器中名称=userMapper的Bean,不存在则按UserMapper类型匹配@ResourceprivateUserMapperuserMapper;}
② 手动指定 Bean 名称,解决多实现冲突
@ServicepublicclassOrderService{// 强制使用名称为wechatPay的实现类@Resource(name="wechatPay")privatePayHandlerpayHandler;}
4)适用场景
  1. 追求 Java 标准,不想强耦合 Spring 专属注解;

  2. 老项目 JavaEE、JNDI 资源兼容场景;

  3. 团队统一规范,习惯通过变量名区分不同实现 Bean;

  4. 未来可能迁移至其他非 Spring 容器的中间件基础层。

5)缺点
  1. 不支持构造注入,无法搭配final实现不可变对象;

  2. 没有可选注入required=false功能;

  3. 多实现类灵活性弱于@Autowired + @Qualifier;

  4. 无法标注构造器,不能使用 Spring 最优构造注入方案。

2.3 @RequiredArgsConstructor(Lombok 构造生成注解)

1)前置依赖:必须引入 Lombok

Maven 依赖

<dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><version>1.18.30</version><scope>provided</scope></dependency>

IDE 必须安装 Lombok 插件,否则编译报错。

2)底层核心原理

Lombok 在编译期 AST 抽象语法树转换,自动生成构造方法,仅纳入两类字段作为构造参数:

  1. 未初始化的private final修饰成员变量;

  2. @lombok.NonNull标记的字段;
    静态变量、普通非 final 字段不会进入构造;
    @NonNull字段自动生成非空判断,传入 null 直接抛出空指针异常。

3)最简标准业务代码(企业主流写法)
importlombok.RequiredArgsConstructor;importorg.springframework.stereotype.Service;@Service@RequiredArgsConstructorpublicclassUserService{// final字段自动生成构造参数,Spring单构造自动注入,无需@AutowiredprivatefinalUserMapperuserMapper;privatefinalRedisTemplate<String,Object>redisTemplate;}
编译后等价手写代码(Lombok 自动生成)
@ServicepublicclassUserService{privatefinalUserMapperuserMapper;privatefinalRedisTemplate<String,Object>redisTemplate;// 自动生成全final字段构造publicUserService(UserMapperuserMapper,RedisTemplate<String,Object>redisTemplate){this.userMapper=userMapper;this.redisTemplate=redisTemplate;}}
搭配 @NonNull 手动强制非空校验
@Service@RequiredArgsConstructorpublicclassUserService{privatefinalUserMapperuserMapper;@NonNullprivateLogClientlogClient;// 普通变量,不会进入构造privateStringtempStr;}

生成构造内自动添加判空代码:

if(logClient==null){thrownewNullPointerException("logClient is marked non-null but is null");}
4)适用场景(90% 新项目推荐)
  1. Controller、Service、Manager 核心业务层统一规范;

  2. 依赖数量多,不想手写超长构造方法,减少样板代码;

  3. 强制依赖final不可变,规避运行时空指针;

  4. 遵循 Spring 官方构造注入最佳实践,无需重复写@Autowired;

  5. 频繁新增 / 删除依赖,构造方法自动同步,无需手动修改。

5)限制与坑
  1. 项目不允许引入 Lombok 时完全无法使用;

  2. 类存在多个手写构造器时,Spring 无法识别注入构造,必须手动给目标构造加@Autowired;

  3. 无法实现可选依赖注入(所有 final 依赖强制必须存在);

  4. 静态变量不会参与构造生成。

三、三大注解相同点(面试高频简答题)

  1. 服务统一目标:全部依托 Spring IoC 容器实现依赖自动装配,手动管理对象创建,降低代码耦合;

  2. 使用范围一致:均用于@Service/@Controller/@Component等 Spring 托管 Bean 内部;

  3. 注入能力互通:均可注入容器内所有 Bean:Mapper、Service、RedisTemplate、配置 Bean、第三方工具类;

  4. 默认强制校验:无特殊配置时,缺失对应 Bean 都会抛出异常,阻止项目正常启动;

  5. 设计思想统一:遵循依赖倒置、面向接口编程,方便单元测试 Mock 替换依赖;

  6. 最终效果一致:注入完成后,类内部可直接调用依赖方法,无需实例化。

四、全方位核心差异对比表(面试背诵版)

对比维度@Autowired@Resource@RequiredArgsConstructor
来源框架Spring 专属JSR-250 Java 标准Lombok 工具
核心职责标记依赖,执行注入逻辑标记依赖,执行注入逻辑编译生成构造方法,不参与注入
匹配顺序先 byType,后 byName先 byName,后 byType无匹配逻辑,仅提供构造参数
支持构造注入✅ 完全支持❌ 禁止标注构造✅ 间接实现构造注入(主流)
可选依赖支持 required=false不支持不支持,全部强制依赖
final 字段兼容字段注入无法 final无法 final强制搭配 final,推荐写法
多实现解决方案@Qualifier 灵活指定name 属性指定,灵活性差配合 @Autowired+Qualifier 使用
第三方依赖仅依赖 SpringJDK 内置无依赖必须引入 Lombok
多容器兼容仅 Spring 可用跨 IoC 容器通用依赖 Spring+Lombok 双环境
空值自动校验无无@NonNull 字段自动判空抛 NPE

五、分场景标准选型规范(直接用作团队编码规范)

场景 1:业务 Service、Controller、Manager(首选)

方案:@RequiredArgsConstructor + private final 字段
优势:代码极简、不可变、符合 Spring 官方推荐、无冗余 @Autowired,统一团队风格。

@RestController@RequiredArgsConstructorpublicclassUserController{privatefinalUserServiceuserService;}

场景 2:存在可选依赖(组件可有可无,不阻塞启动)

方案:@Autowired (required = false) 字段 /setter 注入

@Autowired(required=false)privateMonitorClientmonitorClient;

场景 3:接口多个实现类,需要精准控制 Bean

方案:@Autowired + @Qualifier

@Autowired@Qualifier("wxPayHandler")privatePayHandlerpayHandler;

场景 4:项目禁止引入 Lombok

方案:手写构造 + @Autowired

@ServicepublicclassUserService{privatefinalUserMapperuserMapper;@AutowiredpublicUserService(UserMapperuserMapper){this.userMapper=userMapper;}}

场景 5:兼容 JavaEE 标准、后续可能更换 IoC 容器

方案:@Resource (name=“beanName”)

@Resource(name="dataSource")privateDataSourcedataSource;

场景 6:传统 JNDI、老 Web 项目迁移

方案:统一使用 @Resource

六、高频踩坑避坑指南

  1. @RequiredArgsConstructor 与 @NoArgsConstructor 不能同时使用
    同时生成无参 + 有参两个构造,Spring 启动时无法判定使用哪个注入,直接报错。

  2. 手写多个构造方法时,Lombok 生成构造无法自动注入
    解决方案:手动给 Lombok 生成的构造添加@Autowired。

  3. @Resource 不能写在构造方法上
    强行标注直接编译报错,想要构造注入只能换另外两种方案。

  4. final 字段不能使用字段注入(@Autowired/@Resource)
    final 字段必须在构造时赋值,字段注入时机晚于构造,编译报错。

  5. 混用字段注入与 @RequiredArgsConstructor,代码风格混乱
    规范:统一全部使用 final+@RequiredArgsConstructor,杜绝零散 @Autowired 字段。

  6. @Autowired 多实现类不添加 @Qualifier,启动抛出 NoUniqueBeanDefinitionException
    同类型多个 Bean,Spring 无法选择注入对象,必须指定区分标识。

七、面试高频问答(背诵版)

1. @Autowired 和 @Resource 区别?

  1. 来源:Autowired 是 Spring,Resource 是 JSR-250 Java 标准;

  2. 匹配顺序:Autowired 按类型优先,Resource 按名称优先;

  3. 支持位置:Autowired 支持构造,Resource 仅字段 /setter;

  4. 可选依赖:Autowired 有 required=false,Resource 无;

  5. 跨容器:Resource 兼容性更强。

2. @RequiredArgsConstructor 作用?和 @Autowired 关系?

@RequiredArgsConstructor 是 Lombok 注解,编译生成 final/@NonNull 字段的构造方法;Spring4.3 单构造无需 @Autowired 自动注入,二者搭配简化构造注入代码;它本身不具备注入能力,依赖 Spring 容器完成装配。

3. Spring 为什么推荐构造注入,不推荐字段注入?

  1. 构造注入可使用 final,对象不可变,避免空指针;

  2. 对象创建时所有依赖必须就绪,提前暴露循环依赖;

  3. 单元测试可直接 new 传参,无需反射注入;

  4. 依赖关系显性化,代码可读性更高。

4. 三个注解推荐使用顺序?

新项目允许 Lombok:@RequiredArgsConstructor>@Autowired>@Resource
禁止 Lombok 项目:构造注入 @Autowired > @Resource

八、全文总结

  1. @Autowired:Spring 全能注入注解,灵活适配可选依赖、多实现类场景,适合各类特殊注入需求;

  2. @Resource:Java 标准规范注解,跨容器兼容,适合老项目、追求框架解耦场景;

  3. @RequiredArgsConstructor:现代 Spring 项目最优解,Lombok 语法糖简化构造注入,业务层统一标准首选;
    开发编码统一规范:业务层全部采用@RequiredArgsConstructor + final构造注入;特殊可选依赖使用@Autowired(required=false);跨容器兼容场景使用@Resource。

相关新闻

  • KPI定了、任务分了,而目标和执行差了十万八千里,企业计划、项目该如何落地?
  • IPXWrapper终极指南:在Windows 10/11上轻松运行经典IPX游戏
  • wimgapi.dll 缺失导致安装或部署失败?Windows 映像组件排查思路

最新新闻

  • 力扣算法题:平分正方形(算法小白每日一题)
  • 钢木组合结构自攻螺钉单剪节点试验研究
  • SpringBoot云边协同|智慧地铁ISCS改造实战第5篇:边缘OPC采集重构|边缘就近网关接入、测点本地降噪预处理、主干带宽减负落地方案
  • iOS OC 项目集成 C++ 算法库完整指南
  • 使用Scraper Studio,告别手写爬虫
  • 会议室预订别再靠群里喊:时间冲突检测、审批、签到一套搞定

日新闻

  • Qwen2.5-Turbo百万上下文实战指南:百炼平台长文本处理全解析
  • 怎么监控对标账号更新,2026年作者监控工作流,5款深度对比
  • EdgeRemover:专业级Windows Edge浏览器管理工具,彻底解决顽固软件卸载难题

周新闻

  • Visual C++运行库修复终极指南:5分钟快速解决Windows软件启动错误
  • 手把手教你构建统计局地区经济数据爬虫:从环境搭建到数据持久化全指南
  • 2026多Agent深度解析:用AI团队替代单一模型,四种架构实战落地

月新闻

  • 【总结】入门篇:50句话让你记住架构核心概念
  • WeChatMsg技术方案解析:实现Mac微信数据自主管理的完整解决方案
  • WeChatMsg:革新性微信数据备份方案,打造你的专属数字记忆库

关于尧图

  • 公司简介
  • 团队介绍
  • 企业文化
  • 荣誉资质

服务项目

  • 定制开发
  • 电商建站
  • UI 设计
  • 运维服务

快速链接

  • 案例展示
  • 建站流程
  • 常见问题
  • 资讯中心

联系方式

  • 📍北京市朝阳区互联网产业园 A 座 10 层
  • 📞400-888-8888
  • ✉️contact@rkmt.cn
  • 🕐周一至周日 9:00-21:00

© 2024 北京尧图网络科技有限公司 版权所有 | 京 ICP 备 XXXXXXXX 号