展开菜单
首页 精品内容 本月促销 装机必备 Windows PDF教程 macOS软件 IOS软件 Android AI 专题
全部分类

当前位置:

首页 > 编程开发 > @Autowired 与 @Resource 区别详解

@Autowired 与 @Resource 区别详解

@Autowired按类型注入,需@Qualifier或@Primary解决多实例歧义;@Resource优先按名称注入,名称不匹配时按类型,更利于名称明确的场景。

本文目录

    @Autowired按类型注入,需@Qualifier或@Primary解决多实例歧义;@Resource优先按名称注入,名称不匹配时按类型,更利于名称明确的场景。

    @Autowired 和 @Resource 注解的区别是什么?

    @Autowired 侧重于按类型进行依赖注入,是 Spring 框架特有的;而 @Resource 则优先按名称进行注入,是 Java EE 规范的一部分,可以脱离 Spring 独立使用。

    解决方案

    理解 @Autowired 和 @Resource 的区别,说到底就是理解它们在查找和匹配依赖时的策略差异。

    @Autowired:Spring 的类型优先策略

    @Autowired 是 Spring 框架提供的注解,它的核心思想是“按类型装配”(by type)。当你在一个字段、构造器或 Setter 方法上使用 @Autowired 时,Spring 容器会尝试在它管理的 Bean 中找到一个类型匹配的 Bean 来进行注入。

    例如:

    @Component
    public class MyService {
        @Autowired
        private MyRepository myRepository; // Spring会寻找MyRepository类型的Bean
        // ...
    }

    这里,Spring 会在容器中查找 MyRepository 接口或类的实现。如果容器中只有一个 MyRepository 类型的 Bean,那么它就会被成功注入。但如果容器中有多个 MyRepository 类型的 Bean(比如 MyRepositoryImplA 和 MyRepositoryImplB 都实现了 MyRepository 接口),Spring 就会感到困惑,抛出 NoUniqueBeanDefinitionException 异常,因为它不知道该注入哪一个。

    为了解决这种歧义,你可以配合 @Qualifier 注解,明确指定要注入的 Bean 的名称:

    @Component
    public class MyService {
        @Autowired
        @Qualifier("myRepositoryImplA") // 明确指定Bean的名称
        private MyRepository myRepository;
        // ...
    }

    或者,你也可以将其中一个实现类标记为 @Primary,告诉 Spring 在有多个相同类型的 Bean 时,优先选择这个:

    @Component
    @Primary
    public class MyRepositoryImplA implements MyRepository { /* ... */ }
    
    @Component
    public class MyRepositoryImplB implements MyRepository { /* ... */ }
    
    // MyService中无需@Qualifier,Spring会默认注入MyRepositoryImplA
    @Component
    public class MyService {
        @Autowired
        private MyRepository myRepository;
        // ...
    }

    @Resource:Java EE 的名称优先策略

    @Resource 注解是 JSR-250 规范的一部分,这意味着它不局限于 Spring 框架,也可以在其他 Java EE 容器(如 Tomcat、Glassfish)中使用。它的默认行为是“按名称装配”(by name)。

    当你在一个字段或 Setter 方法上使用 @Resource 时,它的查找顺序是这样的:

    1. 按名称查找: 默认情况下,@Resource 会尝试将注解所在字段的名称(或者 Setter 方法对应的属性名)作为 Bean 的名称去容器中查找。
      @Component
      public class MyService {
          @Resource
          private MyRepository myRepositoryImplA; // 会尝试查找名为"myRepositoryImplA"的Bean
          // ...
      }

      如果找到了,就注入。

    2. 按类型查找: 如果按名称没有找到匹配的 Bean,@Resource 就会退而求其次,尝试按类型进行查找。如果找到一个类型匹配的 Bean,就注入。如果找到多个类型匹配的 Bean,它会抛出异常。

    你也可以通过 @Resource 的 name 属性明确指定要注入的 Bean 的名称:

    @Component
    public class MyService {
        @Resource(name = "myRepositoryImplA") // 明确指定Bean的名称
        private MyRepository myRepository;
        // ...
    }

    或者通过 type 属性指定类型,但这通常不如 name 属性常用,因为名称匹配是其核心优势:

    @Component
    public class MyService {
        @Resource(type = MyRepository.class) // 按类型查找
        private MyRepository someRepository;
        // ...
    }

    总结来说,核心差异是:@Autowired 默认是类型优先,需要 Qualifier 辅助名称;@Resource 默认是名称优先,找不到名称再退化到类型。

    Spring Boot开发中,何时优先选择@Autowired,何时选择@Resource?

    在 Spring Boot 的日常开发中,选择 @Autowired 还是 @Resource,这其实更多是一种个人习惯和团队规范的体现,当然,也有些场景会让我倾向于某一个。

    我个人在多数情况下会更倾向于使用 @Autowired。为什么呢?因为 Spring Boot 项目本身就是深度依赖 Spring 框架的,@Autowired 作为 Spring 原生的注解,用起来感觉更“顺滑”,也更符合 Spring 的设计哲学——即通过类型来建立依赖关系。当我在一个纯粹的 Spring 环境中工作时,我希望我的代码能够充分利用 Spring 提供的便利,而 @Autowired 恰好提供了这种简洁和直观的类型匹配能力。特别是当我的接口只有一个实现类时,@Autowired 几乎是零配置,非常方便。如果遇到多实现的情况,@Qualifier 的存在也提供了一个优雅的解决方案。

    然而,在某些特定的场景下,我会发现 @Resource 更有用武之地。比如,当我在处理一些遗留系统,或者与一些第三方库集成时,这些库可能在 Spring 容器中注册了一些名称很明确的 Bean,但它们的类型可能比较通用,或者我只是想通过一个特定的名称来引用它们。这时候,@Resource 的名称优先匹配策略就显得非常直接和清晰,它能够减少潜在的类型匹配混淆。

    再比如,如果我需要在代码中显式地通过一个字符串名称来引用一个 Bean(这在某些动态配置或工厂模式中可能会出现),那么 @Resource(name="beanName") 的表达力就比 @Autowired 结合 @Qualifier("beanName") 显得更直接一些,因为它把“按名称注入”这个意图放在了注解本身。

    另外,从代码的可移植性角度看,@Resource 因为是 Java EE 规范的一部分,理论上它的代码可以更容易地迁移到其他支持 JSR-250 的 Java EE 容器中。尽管在 Spring Boot 项目中,这种可移植性优势往往被淡化了(因为你已经选择了 Spring),但对于那些对规范性有较高要求,或者未来有潜在迁移需求的项目,@Resource 确实提供了一种更标准化的选择。

    所以,我的经验是:对于大多数 Spring Boot 应用的内部组件依赖,@Autowired 是一个非常好的默认选择;而当涉及到与外部系统集成、处理遗留代码、或者需要通过明确名称来消除歧义时,@Resource 会是更稳健和清晰的选择。

    如果存在多个相同类型的Bean,这两种注解会如何处理?

    处理多个相同类型的 Bean,是我们在 Spring 开发中经常会遇到的一个挑战,也是区分 @Autowired 和 @Resource 行为的关键点。

    @Autowired 的处理方式:

    当 Spring 容器中存在多个类型相同的 Bean,而你又使用了 @Autowired 进行注入时,如果没有额外的指示,Spring 会感到“不知所措”,因为它不知道应该选择哪一个 Bean。在这种情况下,它会抛出一个 NoUniqueBeanDefinitionException 异常。这个异常会明确告诉你,容器中找到了多个符合类型的 Bean,需要你进行进一步的明确。

    为了解决这个问题,通常有以下几种方法:

    1. 使用 @Qualifier: 这是最常用也最推荐的方式。通过在 @Autowired 的同时加上 @Qualifier("beanName"),你可以明确告诉 Spring 要注入哪个具体名称的 Bean。

      @Service("smsSender")
      public class SmsSender implements MessageSender { /* ... */ }
      
      @Service("emailSender")
      public class EmailSender implements MessageSender { /* ... */ }
      
      @Component
      public class NotificationService {
          @Autowired
          @Qualifier("emailSender") // 明确指定注入名为 "emailSender" 的Bean
          private MessageSender messageSender;
      }
    2. 使用 @Primary: 如果你希望在多个相同类型的 Bean 中,有一个是默认优先被注入的,你可以将该 Bean 标记为 @Primary。这样,当 Spring 遇到类型冲突时,会优先选择带有 @Primary 注解的 Bean。

      @Service
      @Primary // 优先选择这个发送器
      public class DefaultSmsSender implements MessageSender { /* ... */ }
      
      @Service
      public class BackupEmailSender implements MessageSender { /* ... */ }
      
      @Component
      public class NotificationService {
          @Autowired // 会自动注入 DefaultSmsSender
          private MessageSender messageSender;
      }
    3. 通过参数名匹配(作为后备): 如果没有 @Qualifier 也没有 @Primary,Spring 还会尝试将要注入的字段名或参数名作为 Bean 的名称进行匹配。但这种方式不如前两种明确,且容易引发混淆,我个人不太推荐在多 Bean 场景下依赖它。

    @Resource 的处理方式:

    @Resource 在处理多个相同类型的 Bean 时,其行为逻辑有所不同,因为它本身就是名称优先的。

    1. 优先按名称查找: 当你使用 @Resource 注解时,它会首先尝试根据字段名(或 Setter 方法名)来查找 Bean。如果找到了一个名称匹配的 Bean,即使有多个相同类型的 Bean,它也会直接注入这个名称匹配的 Bean,不会引发歧义。

      @Service("smsSender")
      public class SmsSender implements MessageSender { /* ... */ }
      
      @Service("emailSender")
      public class EmailSender implements MessageSender { /* ... */ }
      
      @Component
      public class NotificationService {
          @Resource // 尝试查找名为 "smsSender" 的Bean
          private MessageSender smsSender;
      
          @Resource // 尝试查找名为 "emailSender" 的Bean
          private MessageSender emailSender;
      }
    2. 如果按名称未找到,再按类型查找: 如果 @Resource 没有通过名称找到匹配的 Bean,它才会退而求其次,尝试按类型进行查找。在这种情况下,如果容器中存在多个相同类型的 Bean,并且它们都没有被 @Resource 的名称属性明确指定,那么 @Resource 同样会抛出异常,因为它无法决定注入哪一个。

    所以,从处理多 Bean 的角度看,@Resource 在一开始就通过名称匹配的策略,能够在很多情况下避免歧义。而 @Autowired 则需要你显式地通过 @Qualifier 或 @Primary 来解决这种歧义。

    从代码可移植性和规范性角度,这两种注解有何优劣?

    谈到代码的可移植性和规范性,@Autowired 和 @Resource 确实展现出了不同的哲学和定位。

    @Autowired:Spring 框架的深度整合与便捷性

    • 优点:
      • 与 Spring 深度整合: @Autowired 是 Spring 框架的核心组成部分,它与 Spring 的 IoC 容器、AOP、事务管理等功能无缝集成。在纯 Spring 或 Spring Boot 项目中,使用 @Autowired 感觉非常自然,也最能体现 Spring 的“约定优于配置”理念。
      • 简洁性: 对于大多数只有单一实现类的接口,@Autowired 几乎是零配置,代码非常简洁。
      • 类型安全: 默认的类型匹配策略在编译时就能发现一些潜在的类型不匹配问题(当然,运行时找不到 Bean 还是会报错)。
    • 缺点:
      • 框架耦合度高: 这是最主要的“劣势”。@Autowired 是 Spring 特有的注解,如果你的代码将来需要从 Spring 容器迁移到其他非 Spring 的 IoC 容器(比如一个纯 Java EE 容器,或者一个自定义的轻量级容器),那么所有使用了 @Autowired 的地方都需要进行修改。这会增加迁移成本。当然,在实际的 Spring Boot 项目中,这种迁移的可能性通常很低,因为 Spring Boot 本身就意味着对 Spring 生态的深度依赖。
      • 默认行为可能引发歧义: 如前所述,在存在多个相同类型的 Bean 时,@Autowired 默认会报错,需要额外的 @Qualifier 或 @Primary 来解决。

    @Resource:Java EE 标准的通用性与规范性

    • 优点:
      • 高可移植性: 这是 @Resource 最显著的优势。作为 JSR-250 规范的一部分,@Resource 是 Java EE 容器的标准注解。这意味着使用了 @Resource 的代码理论上可以在任何支持 JSR-250 的 Java EE 容器中工作,而不仅仅局限于 Spring。对于那些需要考虑跨平台或未来可能迁移到不同容器的场景,@Resource 提供了一层抽象,降低了框架锁定的风险。
      • 规范性: 遵循 Java EE 规范,使得代码在宏观上更具“标准”感,这对于一些对架构规范有严格要求的企业或项目来说可能是一个加分项。
      • 名称优先的清晰性: 其默认的名称匹配策略在很多情况下能够更直观地表达注入意图,尤其是在 Bean 名称具有明确业务含义时。
    • 缺点:
      • 与 Spring 框架的集成不如 @Autowired 紧密: 尽管 Spring 完全支持 @Resource,但它毕竟不是 Spring 原生的。在某些 Spring 特有的高级特性或扩展点上,@Autowired 可能表现得更自然。
      • 在 Spring Boot 环境下,可移植性优势可能被弱化: 就像我前面说的,一旦你选择了 Spring Boot,你通常就已经接受了对 Spring 框架的深度依赖。在这种情况下,@Resource 的可移植性优势在实践中可能并不那么突出。

    我的看法:

    在我的实际开发经验中,如果项目是全新的 Spring Boot 应用,且不预期有任何脱离 Spring 框架的可能,我通常会选择 @Autowired。它更符合 Spring 的编程模型,也更简洁。然而,如果我正在维护一个老项目,或者一个需要与多种技术栈集成的模块,或者团队对 Java EE 规范有特别的偏好,那么 @Resource 就会成为一个非常有吸引力的选择。它提供了一种更标准化的依赖注入方式,让代码看起来更“规矩”一些,也为未来的不确定性留下了一定的缓冲空间。最终的选择,往往是团队技术栈、项目需求和个人偏好综合权衡的结果。

    本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系bd@zhengruan.com
    作者最新文章
    编程开发 Java
    相关文章 更多
    精品专题 更多
    装机必备

    正软商城装机必备专区,精选办公、浏览器、安全防护、影音播放、压缩解压、设计创作和系统工具等电脑常用正版软件,帮助用户快速完成新电脑软件配置。

    Windows

    正软商城Windows软件专区,汇集适用于Windows电脑的办公、设计、安全防护、影音播放、开发工具和系统优化软件,提供软件介绍、系统要求、正版授权及购买下载服务。

    PDF教程

    正软商城PDF教程频道提供PDF编辑、转换、合并、拆分、压缩及格式处理方法,同时介绍常用PDF软件和工具的使用技巧。

    macOS软件

    正软商城macOS软件专区,精选适用于Mac电脑的办公、设计、影音、效率、开发和系统工具,提供软件功能介绍、macOS兼容版本、正版授权及购买下载服务。

    IOS软件

    正软商城iOS软件专区,精选适用于iPhone和iPad的办公、学习、影音、设计、效率及AI应用,提供功能介绍、适用设备、系统要求和正版获取方式等信息。

    AI

    正软商城AI软件专区,汇集AI写作、AI绘画、AI视频、AI办公、AI编程、AI翻译、智能客服和数据分析等人工智能工具,提供功能介绍、适用平台、收费方式及正版购买信息。

    Mac软件 更多
    Aperty macOS版
    Aperty macOS版

    Aperty 是 Skylum 推出的 AI 人像修图软件,支持自然肤质修饰、瑕疵处理、面部与身体调整、预设及批量同步。

    火山引擎 网页版
    火山引擎 网页版

    火山引擎是字节跳动旗下企业级云与AI服务平台。聚焦大模型核心能力,依托字节自研豆包多模态大模型,凭借火山方舟一站式平台,提供模型精调、推理部署、智能应用搭建等全链路服务,结合高性能AI算力,助力各行业快速落地大模型数字化与智能化应用。

    立刻MV 网页版
    立刻MV 网页版

    立刻MV 面向音乐人、内容创作者和品牌团队,帮助用户低成本完成歌曲 MV、歌词视频、AI 分镜、图生视频与最终合成。

    蛙蛙写作 网页版
    蛙蛙写作 网页版

    蛙蛙写作 AI 创作工具,覆盖小说、剧本、文案,一键生成文稿,打通文字转视频全流程,高效解决创作难题。

    讯飞智作 网页版
    讯飞智作 网页版

    讯飞智作是一款基于语音合成技术、虚拟人驱动技术与数字人形象声音构建能力的 AI 数字人音视频创作平台。

    超级简历WonderCV 网页版
    超级简历WonderCV 网页版

    超级简历WonderCV是面向应届生和AI小白的智能求职平台,覆盖简历、面试与职业规划。

    音述AI 网页版
    音述AI 网页版

    音述AI,是一个以“用声音述说故事”为核心的 AI 音乐创作与声音分享社区。

    AionClaw macOS版
    AionClaw macOS版

    AionClaw 是可在桌面端运行的任务型 AI 助手,通过数字专家与技能市场组合办公、创作、数据和开发能力。

    Loomy macOS版
    Loomy macOS版

    Loomy 是科大讯飞推出的桌面 AI 助手,可通过对话、任务与工作目录协助处理办公、内容创作和资料整理。

    AirBuddy 3 macOS版
    AirBuddy 3 macOS版

    AirBuddy 3 是面向 macOS 的蓝牙外设增强工具,可集中查看 AirPods、Beats 与苹果设备电量,提供快速连接、播放控制、电量提醒、桌面小组件和多台 Mac 外设接力等功能。

    AirServer macOS版
    AirServer macOS版

    AirServer macOS版可把 Mac 转换为无线投屏接收端,通过 AirPlay 或 Google Cast 接收手机、平板和电脑画面,并支持多设备同时连接、高清镜像及会话录制,适合家庭娱乐、课堂教学、会议演示和应用展示。

    AnyDesk macOS版
    AnyDesk macOS版

    AnyDesk macOS版是一款适用于远程办公、设备维护和客户支持的远程桌面工具,可连接并操作异地计算机,支持文件传输、无人值守访问、会话权限控制及跨平台协作。

    WINDOWS 更多
    讯飞绘文 网页版
    讯飞绘文 网页版

    讯飞绘文网页版是科大讯飞推出的AI图文创作与内容运营工具,覆盖热点选题、文章生成、稿件校对、智能配图、排版发布和数据复盘等环节,适合自媒体创作者及内容团队在线使用。

    Maya(Autodesk Maya) Windows版
    Maya(Autodesk Maya) Windows版

    Autodesk Maya 是面向影视、电视、动画和游戏行业的专业三维制作软件,集多边形与 NURBS 建模、角色绑定、关键帧和动作捕捉动画、Bifrost 特效模拟、材质开发及 Arnold 渲染于一体,

    Aperty Windows版
    Aperty Windows版

    Aperty 是 Skylum 推出的 AI 人像修图软件,支持自然肤质修饰、瑕疵处理、面部与身体调整、预设及批量同步。

    火山引擎 网页版
    火山引擎 网页版

    火山引擎是字节跳动旗下企业级云与AI服务平台。聚焦大模型核心能力,依托字节自研豆包多模态大模型,凭借火山方舟一站式平台,提供模型精调、推理部署、智能应用搭建等全链路服务,结合高性能AI算力,助力各行业快速落地大模型数字化与智能化应用。

    立刻MV 网页版
    立刻MV 网页版

    立刻MV 面向音乐人、内容创作者和品牌团队,帮助用户低成本完成歌曲 MV、歌词视频、AI 分镜、图生视频与最终合成。

    蛙蛙写作 网页版
    蛙蛙写作 网页版

    蛙蛙写作 AI 创作工具,覆盖小说、剧本、文案,一键生成文稿,打通文字转视频全流程,高效解决创作难题。

    讯飞智作 网页版
    讯飞智作 网页版

    讯飞智作是一款基于语音合成技术、虚拟人驱动技术与数字人形象声音构建能力的 AI 数字人音视频创作平台。

    超级简历WonderCV 网页版
    超级简历WonderCV 网页版

    超级简历WonderCV是面向应届生和AI小白的智能求职平台,覆盖简历、面试与职业规划。

    音述AI 网页版
    音述AI 网页版

    音述AI,是一个以“用声音述说故事”为核心的 AI 音乐创作与声音分享社区。

    AionClaw Windows版
    AionClaw Windows版

    AionClaw 是可在桌面端运行的任务型 AI 助手,通过数字专家与技能市场组合办公、创作、数据和开发能力。

    Loomy Windows版
    Loomy Windows版

    Loomy 是科大讯飞推出的桌面 AI 助手,可通过对话、任务与工作目录协助处理办公、内容创作和资料整理。

    AirServer Windows版
    AirServer Windows版

    AirServer Windows版可把电脑变成AirPlay、Google Cast和Miracast无线投屏接收端,适合会议演示、课堂教学及家庭大屏分享。发送设备通常无需另装客户端,并可同时接收和智能排列多个镜像会话。