前情回顾
-
正确使用@Autowired
- @Autowired 注解在构造器上的使用规则(字段注入也挺好的)
-
正确使用@Resource
来源不同
-
@Autowired的“爹”是Spring
-
@Resource的“爹”是Java(JSR-250)
- 这是一个规范,Spring对这个注解进行了支持。
- 如果换了其他的框架,大概率用不了@Autowired(除非兼容了),大概率能用@Resource(毕竟是Java规范,框架应该会支持的)
当然了,这一点了解下就行了。毕竟实际开发中用的框架是Spring,这两个注解都能用。
查找bean的方式不同(重点)
简单
-
@Autowired:根据类型去查找bean,如果找到了多个,那么再根据名称去选择注入哪一个。
-
找到了多个,名称是helloService,不匹配,因此不知道注入哪一个。
-
将名称换成helloServiceImpl1,就能唯一匹配bean了。而且IDEA会提示实际注入了哪个bean(见下图的小红框。)
虽然cursor很猛,但在Java领域,IDEA还是王者啊。
-
不过,一般会用另一个注解来指定名称:
/*** @author: Forrest* @since: 2025/3/15*/ @RestController public class HelloController {@Qualifier("helloServiceImpl2")@Autowiredprivate HelloService helloService;@GetMapping("/hello")public String hello() {return helloService.sayHello();} }
- 这个还是有使用场景的,例如要重构了,从helloServiceImpl1切换为helloServiceImpl2。当然了,如果很多地方都用到了helloService,这样修改是不方便的,应该在helloService的实现中完成路由,即helloServiceImpl1内部切换为helloServiceImpl2。(这样想,Service层的约定:接口 + 实现,非常鸡肋…)
-
-
@Resource:根据名称去查找bean,未找到,再根据类型去查找,如果找到多个,会抛异常。
左侧查看实际注入时,会发现有两个bean。
-
指定名称:
-
用@Qualifier更合适
/*** @author: Forrest* @since: 2025/3/15*/ @RestController public class HelloController {@Qualifier("helloServiceImpl2")@Resourceprivate HelloService helloService;@GetMapping("/hello")public String hello() {return helloService.sayHello();} }
-
进阶
@Autowired、@Resource都支持@Primary(Spring Boot 3.3.7)
-
上文提到:@Autowired先根据类型去查找bean,如果找到了多个,选哪一个呢?
-
如果多个bean中,有的bean被打上了@Primary,那么选这个bean。
-
如果多个bean都被打上了@Primary呢?那继续根据名称来筛选。
-
-
对于@Resource,优先按照名称去匹配,如果存在多个,那么匹配被打上@Primary的bean。
要彻底搞明白,还得去看这一块的源码(埋坑)
使用范围不同(挺重要)
特性 | @Autowired | @Resource |
---|---|---|
注解位置 | 可以注解在字段、构造方法、Setter方法及方法参数上 | 可以注解在字段、Setter方法上 |
集合类型注入 | 支持,可以用于注入集合类型(如List<XXX> ),自动注入所有符合类型的Bean | 也支持 |
数组类型注入 | 支持,可以用于注入数组类型,自动注入所有符合类型的Bean | 也支持 |
构造方法注入 | 支持,可以用于构造方法参数的注入 | 不支持构造方法注入 |
注解的参数不同
特性 | @Autowired | @Resource |
---|---|---|
支持的参数 | 只支持required 一个参数 | 支持name 、type 等7个参数 |
依赖存在性 | 默认依赖的Bean必须存在,可以通过required=false 设置为非必须 | 默认依赖的Bean必须存在,不存在会抛出异常 |
-
@Autowired(required = false) 不是说就不注入依赖了,而是一旦注入失败了, 那就不注入了。也就是不要因为弱依赖而影响了主流程。
-
对于@Resource,用的最多的是
name
、type
。-
@Resource默认是按名称去查找bean的,因此,最好用name明确这个名称。
@Resource(type = HelloServiceImpl1.class) private HelloService helloService;
-