/**
* 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.
*
* @author Mark Fisher
* @author Juergen Hoeller
* @since 2.5
* @see Autowired
*/
@Target({ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER, ElementType.TYPE, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
public @interface Qualifier {
String value() default "";
}
源码中注释的部分翻译过来就是:
此注释可在字段或参数上,用作自动连线时的候选bean。它也可用于其他自定义注解上,该自定义注解可以当作一个Qualifier。
上面这句话就是说明两个功能:
(1)使用@Autowired自动注入的时候,可以在属性或参数加上@Qualifier(“xxx”)指定注入到对象;
(2)可以作为筛选的限定符,我们在写自定义的注解时,可以在其定义上增加@Qualifier,在自动注入时,来筛选需要的对象。也可以直接使用Qualifier注解来实现类的筛选
这种用法比较常见,比如一个Animal接口,有多个实现,@Autowired注入到时候,可以使用@Qualifier指定哪个bean生效。
public interface Animal {
void say(String word);
}
-------
@Component
public class Dog implements Animal {
@Override
public void say(String word) {
System.out.println("汪汪");
}
}
-------
@Component
public class Cat implements Animal {
@Override
public void say(String word) {
System.out.println("喵喵");
}
}
-------
@SpringBootTest(classes = {AutodeliverApplication8090.class})
@RunWith(SpringJUnit4ClassRunner.class)
public class AutodeliverApplication8090Test {
@Autowired
@Qualifier("dog")
private Animal animals;
@Test
public void testAutoInject(){
animal.say("123");
}
运行测试代码后,控制台打印汪汪,既自动注入了Dog类
对上面的代码做一些改动,加入一个自定义注解@MyMark
public interface Animal {
void say(String word);
}
-------
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD, ElementType.METHOD, ElementType.TYPE})
@Qualifier
public @interface MyMark {
}
-------
@Component
@MyMark
public class Dog implements Animal {
@Override
public void say(String word) {
System.out.println("汪汪");
}
}
-------
@Component
@MyMark
public class Cat implements Animal {
@Override
public void say(String word) {
System.out.println("喵喵");
}
}
-------
@Component
public class Fish implements Animal {
@Override
public void say(String word) {
System.out.println("鱼鱼");
}
}
-------
@SpringBootTest(classes = {AutodeliverApplication8090.class})
@RunWith(SpringJUnit4ClassRunner.class)
public class AutodeliverApplication8090Test {
@Autowired
@MyMark // 筛选功能,在自动注入的属性上要加注解,且注入的属性类型为集合
private List<Animal> animals;
@Test
public void testAutoInject(){
for(Animal animal: animals){
animal.say("123");
}
}
运行后,控制台打印,汪汪,喵喵,没有打印鱼鱼,因为只有Dog和Cat类使用了@MyMark。这里直接把代码种的@MyMark注解换成@Qualifier注解,是一样的效果。
注意:筛选功能,在自动注入的属性上要加注解,且注入的属性类型为集合。
另外,@Qualifier注解是可以指定value的,这样我们可以通过values来分类筛选想要的对象了,这里不列举代码了,感兴趣的同学自己试试。
我们使用ribbon的时候一般都有类似这样的代码:
@Configuration
public class RestTemplateConfiguration {
@Bean
@LoadBalanced
public RestTemplate getRestTemplate(){
return new RestTemplate();
}
}
疑问:为什么这里加上@LoadBalanced既可以实现负载均衡呢?答案就在@LoadBalanced里。
@Target({ ElementType.FIELD, ElementType.PARAMETER, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@Qualifier
public @interface LoadBalanced {
}
@LoadBalanced注解上加了@Qualifier注解,在程序启动初始化的时候,在spring配置类
LoadBalancerAutoConfiguration中会筛选出来所有加了@LoadBalanced注解的RestTemplate对象,执行http请求的时候就可以从按负载均衡规则从list选择RestTemplate执行实际的请求,这样就达到负载均衡的目的。
谢谢你的阅读,如果你喜欢这篇文章,请进行点赞,评论,收藏!