@Autowired 注解与 @Resource 注解有什么区别?

本文详细介绍了Spring框架中的@Autowired和@Resource注解的区别与使用。@Autowired默认按照类型(byType)装配,而@Resource默认按照名称(byName)。在遇到多个相同类型的Bean时,可以使用@Qualifier或@Resource的name属性来指定特定Bean。同时,文章还讨论了如何处理@Autowired在Mybatis中的应用问题。

答:

首先,二者的相同点为:

@Autowired 与 @Resource 注解都可以用来装配 Bean;且,二者都可以写在字段上,也可以写在 setter 方法上。

二者的不同点:

@Autowired 注解是由 Spring 框架提供,而 @Resource 注解则是 javax.annotation.Resource 提供,也就是 J2EE 的标准,但是 Spring 支持该注解注入 Bean。

@Autowired 注解默认按照 Bean 类型 (byType) 装配依赖的 Bean,默认的情况下,它要求依赖的对象必须存在,默认是不允许 null 值的,如果想要设置允许 null 值,可以设置它的 required 属性为 false。最常见的问题就是 IDEA 中, Mybatis 的 mapper 接口使用 @Autowired 引入会出现错误提示:

这种情况下,设置 required 属性为 false,即可解决问题

而 @Resource 注解默认按照 Bean 名字 (byName) 来装配依赖的 Bean。@Resource 有两个属性比较重要,分别是 name 与 type 。

 扫VX 领Java资料,前端,测试,python等等资料都有

@Resource 装配 Bean 的原则:

如果没有指定 name 与 type 属性,即,默认情况按照 byName 进行装配
如果同时指定了 name 与 type 属性,则从 Spring 上下文中找到名称与类型都唯一匹配的 Bean 进行装配,找不到则抛出异常
如果仅指定了 name 属性,则从 Spring 上下文中查找名称匹配的 Bean 进行装配,找不到则抛出异常
如果仅指定了 type 属性,则从 Spring 上下文中查找类型匹配的,唯一的 Bean 进行装配,找不到或找到多个都会抛出异常
既然我们在上文中提到了 @Qualifier 注解,接下来就看下该注解的基本用法。

@Qualifier 注解限定哪个 Bean 应该被自动注入,该注解有助于消除歧义 Bean 的自动注入,举个例子:

MyService

public interface MyService{ 
    // ...
}
MyServiceImpl1

@Service
public class MyServiceImpl1 implements MyService {
  // ...
}
MyServiceImpl2

@Service
public class MyServiceImpl2 implements MyService {
  // ...
}
当我们在 Controller 中将 MyService 服务注入进来时,因为有 MyService 的两个实现类,所以我们应该使用 @Qualifier 注解限定哪个实现类应该被注入:

@Controller
public class MyController {
    @Autowired
    @Qualifier("MyServiceImpl1") // 指定 MyServiceImpl1 应该被注入
    private MyService myService;

    // ...
}
@Qualifier 另一个常用的实践是可以让 @Autowired 注解按照 byName 来装配对象,示例如下:

public class Test {
    @Autowired
    @Qualifier("userDao")
    private UserDao userDao;
    // ...
}

 扫VX 领Java资料,前端,测试,python等等资料都有

<think>我们正在讨论Spring框架中的两个重要注解@Autowired@Resource。用户明确询问了它们之间的区别以及使用场景。根据之前的对话历史,用户已经对Spring的依赖注入有了基本了解,现在需要更深入的对比。首先回忆这两个注解的核心区别@Autowired是Spring特有的注解,而@ResourceJava标准注解(JSR-250)。这个根本差异会影响它们的使用方式和兼容性。在依赖注入机制上,@Autowired默认按类型匹配。例如当需要注入一个MileageRateService接口时,Spring会查找实现该接口的Bean。如果有多个实现,就需要配合@Qualifier指定名称。而@Resource默认按名称匹配,它先按指定的name属性查找,如果没有指定name则按字段名或属性名查找。使用场景也有差异。@Autowired更灵活,支持required属性设置非强制依赖,还能用在构造器或方法上实现特殊注入逻辑。@Resource则在需要按名称注入时更直观,特别是当存在多个同类型Bean时。考虑用户可能遇到的常见问题:如果同时使用这两个注解注入同名字段会怎样?实际测试表明Spring会优先处理@Resource,因为它的处理顺序更靠前。不过最好避免混用。最后思考如何组织回答结构。先以表格形式清晰对比核心差异,再分别说明典型用法,最后给出选择建议。特别要强调在SpringBoot项目中两者都能用,但团队最好统一风格。</think>### `@Autowired` `@Resource` 的区别及使用场景 在 Spring 依赖注入中,`@Autowired` 和 `@Resource` 是两种核心注解,但它们在来源、注入机制和使用场景上存在显著差异。以下是详细对比: | **特性** | **@Autowired** (Spring 特有) | **@Resource** (JSR-250 标准) | |------------------|-------------------------------------------|--------------------------------------| | **来源** | Spring 框架原生注解 | Java 标准注解 (`javax.annotation`) | | **默认注入机制** | **按类型匹配** (byType) | **按名称匹配** (byName) | | **名称指定方式** | 需配合 `@Qualifier("beanName")` | 直接通过 `name` 属性 (`@Resource(name="beanName")`) | | **是否支持构造器注入** | ✅ | ❌ (仅支持字段/Setter方法) | | **是否支持`required`** | ✅ (`@Autowired(required=false)`) | ❌ | | **适用场景** | 优先类型匹配、构造器注入、Spring 生态集成 | 多实现类时精确指定 Bean、跨框架兼容性 | --- #### 一、核心差异详解 1. **注入机制不同** - **@Autowired** 默认按**类型匹配**。例如注入 `MileageRateService` 接口时,Spring 会查找该接口的唯一实现: ```java @Autowired private MileageRateService rateService; // 需确保仅一个实现类 ``` 若存在多个实现,需用 `@Qualifier` 指定: ```java @Autowired @Qualifier("primaryRateService") // 指定 Bean 名称 private MileageRateService rateService; ``` - **@Resource** 默认按**名称匹配**。直接通过字段名或 `name` 属性查找 Bean: ```java @Resource // 匹配名为 "rateService" 的 Bean private MileageRateService rateService; @Resource(name = "backupRateService") // 显式指定名称 private MileageRateService backupService; ``` 2. **依赖处理能力** - **@Autowired** 支持更灵活的注入方式: - **构造器注入**(推荐): ```java @Service public class PaymentService { private final RateService rateService; @Autowired // 可省略(Spring 4.3+) public PaymentService(RateService rateService) { this.rateService = rateService; } } ``` - **集合注入**(自动收集所有实现类): ```java @Autowired private List<RateService> allRateServices; // 注入所有实现类 ``` - **@Resource** 仅支持字段或 Setter 方法注入: ```java @Resource public void setRateService(RateService rateService) { this.rateService = rateService; } ``` 3. **异常处理** - **@Autowired** 默认要求依赖必须存在(`required=true`)。若允许缺失,需显式设置: ```java @Autowired(required = false) // 找不到 Bean 时不报错 private Optional<RateService> optionalRateService; ``` - **@Resource** 找不到 Bean 时**直接抛出异常**,无 `required` 选项。 --- #### 二、使用场景建议 | **场景** | **推荐注解** | **原因** | |------------------------------|-------------------|--------------------------------------| | 精确指定 Bean 名称 | `@Resource` | 直接通过 `name` 属性控制,更简洁 | | 构造器注入 | `@Autowired` | 唯一支持构造器注入注解 | | 跨框架兼容(如 Jakarta EE) | `@Resource` | Java 标准,非 Spring 项目也可用 | | 按类型自动收集所有实现类 | `@Autowired` | 支持集合注入 (`List<Interface>`) | | 可选依赖(允许为 `null`) | `@Autowired` | 通过 `required=false` 灵活控制 | --- #### 三、最佳实践 1. **Spring Boot 项目** - 优先使用 `@Autowired` + 构造器注入,提升代码可测试性和安全性[^1]。 - 多实现类时,用 `@Qualifier` 或 `@Primary` 辅助解决冲突。 2. **兼容性要求高的项目** - 若需兼容非 Spring 容器(如 Jakarta EE),选择 `@Resource`。 3. **避免混用** ```java // ❌ 避免混用(可能导致注入行为混乱) @Autowired @Resource(name = "serviceA") private Service service; ``` > **关键总结**: > - 需要**类型驱动**或**构造器注入** → 选 `@Autowired` > - 需要**精确名称匹配**或**跨框架兼容** → 选 `@Resource` > - 在 Spring 生态中,`@Autowired` 更灵活;在异构环境中,`@Resource` 更通用。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值