@Autowired 和 @Resource 有什么区别?
@Autowired 和 @Resource 都是 Spring/Spring Boot 项目中,用来进行依赖注入的注解。它们都提供了将依赖对象注入到当前对象的功能,但二者却有众多不同@Autowired 和 @Resource 的区别主要体现在以下 5 点:
- 来源不同;
- 依赖查找的顺序不同;
- 支持的参数不同;
- 依赖注入的用法不同;
- 编译器 IDEA 的提示不同。
1. 来源不同
@Autowired 是 Spring 框架自身提供的注解,自 Spring 2.5 版本引入,它深深植根于 Spring 生态体系,是 Spring 依赖注入功能的核心注解之一,被广泛应用于 Spring 和 Spring Boot 项目中进行对象的依赖注入。而 @Resource 则来源于 JSR-250 规范,这是 Java EE 标准的一部分,由 Java 官方定义。在 Java EE 环境下,以及兼容 Java EE 规范的 Spring 项目中都可以使用 @Resource 来实现依赖注入,因此 @Resource 具有一定的跨容器通用性,不仅能在 Spring 容器中使用,在其他支持 JSR-250 规范的容器中同样适用。
2. 依赖查找的顺序不同
@Autowired 按照类型进行依赖查找。当容器中有多个同一类型的 bean 时,单纯使用 @Autowired 会导致注入歧义,引发 NoUniqueBeanDefinitionException 异常。此时可以结合 @Qualifier 注解,通过指定 bean 的名称来明确注入哪一个具体的 bean 。例如,有两个类型为 UserService 的 bean ,一个名称为 userServiceImpl ,另一个为 adminUserServiceImpl ,若要注入 userServiceImpl ,代码可以这样写:
@Autowired@Qualifier("userServiceImpl")private UserService userService;
而 @Resource 默认按照名称进行查找。如果没有指定名称属性,它会将注入字段的名称或 setter 方法对应的属性名作为 bean 名称在容器中查找。如果找不到同名的 bean ,则会再按照类型进行查找。例如:
@Resourceprivate UserService userService;
上述代码会先查找名称为 userService 的 bean ,若不存在,则查找类型为 UserService 的 bean 。
3. 支持的参数不同
@Autowired 主要有一个 required 参数,用于指定依赖注入是否为必需的。该参数默认为 true ,即表示如果找不到匹配的 bean ,Spring 容器启动时会抛出异常。当将其设置为 false 时,若找不到匹配的 bean ,则注入 null 。示例如下:
@Autowired(required = false)private UserService userService;
@Resource 支持 name 和 type 两个主要参数 。name 参数用于指定要注入的 bean 的名称,type 参数用于指定要注入的 bean 的类型。通常情况下,使用其中一个参数即可满足需求。比如通过 name 指定 bean 名称:
@Resource(name = "userServiceImpl")private UserService userService;
或者通过 type 指定 bean 类型:
@Resource(type = UserService.class)private UserService userService;
4. 依赖注入的用法不同
@Autowired 可以用在字段上,也可以用在 setter 方法上,甚至构造函数上。用在字段上时,代码简洁直观,如:
@Autowiredprivate UserService userService;
用在 setter 方法上:
@Autowired
private UserService userService;
public void setUserService(UserService userService) {this.userService = userService;
}
用在构造函数上:
@Autowiredpublic
private final UserService userService;
MyService(UserService userService) {this.userService = userService;
}
当一个类只有一个构造函数时,@Autowired 注解可以省略,Spring 会自动进行构造函数注入。
@Resource 同样可以用在字段和 setter 方法上,但一般不用于构造函数。用在字段上:
@Resourceprivate UserService userService;
用在 setter 方法上:
@Resource
private UserService userService;
public void setUserService(UserService userService) {this.userService = userService;
}
5. 编译器 IDEA 的提示不同
在使用 IDEA 开发时,对于 @Autowired 注解,当存在注入歧义等潜在问题时,IDEA 会给出相应的警告提示,例如提示开发者添加 @Qualifier 注解来消除歧义。而对于 @Resource 注解,IDEA 的提示相对较少,因为它的查找逻辑相对复杂一些,默认按照名称查找,在很多情况下即使存在潜在问题也不会像 @Autowired 那样明确提示,这就需要开发者对其原理有更深入的理解,避免在开发过程中出现不易察觉的依赖注入问题。
综上所述,@Autowired 和 @Resource 在 Spring/Spring Boot 项目中都有各自的适用场景。开发者在使用时,需要根据项目的具体需求、依赖查找的逻辑以及代码的可读性等多方面因素来选择合适的注解,从而写出更加健壮和易于维护的代码。