https://serms.top/post/7047b0e7/
</div>
这是官方的介绍:
This annotation may be used on a field or parameter as a qualifier for
candidate beans when autowiring. It may also be used to annotate other
custom annotations that can then in turn be used as qualifiers.
简单的理解就是:
(1)在使用@Autowire 自动注入的时候,加上@Qualifier(“test”)
可以指定注入哪个对象;
(2)可以作为筛选的限定符,我们在做自定义注解时可以在其定义上增加@Qualifier,用来筛选需要的对象。这个理解看下面的代码吧,不好解释。
功能介绍
首先是对(1)的理解。
1 2 3 4 5 6 7 8 9 10 11 12 13 14
|
@Configuration public class TestConfiguration { @Bean("testClass1") TestClass testClass1(){ return new TestClass("TestClass1"); } @Bean("testClass2") TestClass testClass2(){ return new TestClass("TestClass2"); } }
|
下面是正常的引用
1 2 3 4 5 6 7 8 9 10 11 12 13
| @RestController public class TestController {
@Autowired @Qualifier("testClass1") private TestClass testClass;
public Object test(){ return testClassList; } }
|
@Autowired 和@Qualifier 这两个注解的连用在这个位置就类似 @Resource(name=“testClass1”)
对(2)的理解
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| @Configuration public class TestConfiguration { @Qualifier @Bean("testClass1") TestClass testClass1(){ return new TestClass("TestClass1"); }
@Bean("testClass2") TestClass testClass2(){ return new TestClass("TestClass2"); } }
|
1 2 3 4 5 6 7 8 9 10 11 12
| @RestController public class TestController { @Autowired List<TestClass> testClassList= Collections.emptyList();
@GetMapping("/test") public Object test(){ return testClassList; } }
|
我们调用得到的结果是
1 2 3 4 5 6 7 8 9
| [ { "name": "TestClass1" }, { "name": "TestClass2" } ]
|
我们可以看到所有的 testclass 都获取到了。接下来我们修改下代码
1 2 3 4 5 6 7 8 9 10 11 12 13
| @RestController public class TestController {
@Qualifier @Autowired List<TestClass> testClassList= Collections.emptyList();
@GetMapping("/test") public Object test(){ return testClassList; } }
|
和上面代码对比就是在接收参数上增加了@Qualifier 注解,这样看是有什么区别,我们调用下,结果如下:
1 2 3 4 5
| [ { "name": "TestClass1" } ]
|
返回结果只剩下增加了@Qualifier 注解的 TestClass 对象,这样我们就可以理解官方说的标记筛选是什么意思了。
另外,@Qualifier 注解是可以指定 value 的,这样我们可以通过 values 来分类筛选想要的对象了,这里不列举代码了~
@Resource 用法与@Autowired
用法 用法相似,也是做依赖注的,从容器中自动获取 bean。但还是有一定的区别。
- 在启动 spring 的时候,首先要启动容器;
- 启动 spring 容器时,会默认寻找容器扫描范围内的可加载 bean,然后查找哪些 bean 上的属性和方法上有@Resource 注解;
- 找到@Resource 注解后,判断@Resource 注解括号中的 name 属性是否为空,如果为空:看 spring 容器中的 bean 的 id 与@Resource 要注解的那个变量属性名是否相同,如相同,匹配成功;如果不相同,看 spring 容器中 bean 的 id 对应的类型是否与@Resource 要注解的那个变量属性对应的类型是否相等,若相等,匹配成功,若不相等,匹配失败。
- 如果@Resource 注解括号中的 name 属性不为空,看 name 的属性值和容器中的 bean 的 id 名是否相等,如相等,则匹配成功;如不相等,则匹配失败。
示例如下:
@Resource 注解注解的 name 属性不为空
首先创建 Person 类,并纳入容器中管理:
1 2 3 4 5 6 7 8 9 10 11
| package com.lzj.springboot.resource; import org.springframework.stereotype.Component;
@Component(value="ps") public class Person {
public void say(){ System.out.println("------say()------"); } }
|
然后创建 Man 类,类中的属性依赖 Person 类型的 bean
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| package com.lzj.springboot.resource; import javax.annotation.Resource; import org.springframework.stereotype.Component;
@Component public class Man {
@Resource(name="ps") private Person person;
public void work(){ person.say(); System.out.println("------work()------"); } }
|
启动类为:
1 2 3 4 5 6 7 8 9 10 11
| @SpringBootApplication(scanBasePackages="com.lzj.springboot") public class App {
public static void main(String[] args) { SpringApplication app = new SpringApplication(App.class); ConfigurableApplicationContext context = app.run(args); context.getBean(Man.class).work(); context.close(); } }
|
启动工程,输出如下:
1 2
| ------say()------ ------work()------
|
@Resource 注解注解的 name 属性为空
1、@Resource 要注解的那个变量属性与容器中的 bean 的 id 的名字相等
启动类和 Person 的类与相面一样,下面直接修改 Man 类如下:
1 2 3 4 5 6 7 8 9 10 11 12 13
| @Component public class Man {
@Resource private Person ps;
public void work(){ ps.say(); System.out.println("------work()------"); } }
|
2、@Resource 要注解的那个变量属性与容器中的 bean 的 id 的名字不相等
启动类和 Person 的类与相面一样,下面直接修改 Man 类如下:
1 2 3 4 5 6 7 8 9 10 11 12
| @Component public class Man {
@Resource private Person person;
public void work(){ person.say(); System.out.println("------work()------"); } }
|