@Qualifier
1. 解释
当Spring中存在多个类型相同但是名称不同的Bean时,使用@Autowired
注解向类的构造方法、方法、参数、字段中注入Bean对象时,首先会根据Bean的类型注入,如果存在多个类型相同的Bean时,会根据Bean的名称注入,如果找不到对应名称的Bean时,就会抛出异常。
对于上述场景,可以通过@Qualifier
注解明确指定要注入的Bean
2. 场景
当项目中集成了多个消息中间件,对外提供同意发送消息的接口,基于RocketMQ、Kafka、RabbitMQ实现的消息发送类上分别标注了不同的Bean名称。如果在业务系统中需要指定使用某种消息中间件来发送消息时,就需要使用@Qualifier
注解来明确指定Bean的名称
3. 源码
java
@Target({ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER, ElementType.TYPE, ElementType.CONSTRUCTOR})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Qualifier
public @interface Qualifier {
// 表示Bean的唯一标识
// 当使用Spring按照类型自动注入式,存在多个类型相同的Bean的时候,就可以使用此注解来明确注入哪个Bean对象
String value() default "";
}
4. Demo
4.1 区分同名Bean
一个接口和两个实现不同名字的实现类
java
public interface PaymentService {
void pay();
}
@Service("creditCardService")
public class CreditCardPaymentService implements PaymentService {
public void pay() {
System.out.println("Paying via Credit Card");
}
}
@Service("paypalService")
public class PaypalPaymentService implements PaymentService {
public void pay() {
System.out.println("Paying via Paypal");
}
}
使用@Qualifier注解,注入想要的Bean
java
@Component
public class PaymentClient {
private final PaymentService paymentService;
@Autowired
public PaymentClient(@Qualifier("creditCardService") PaymentService paymentService) {
this.paymentService = paymentService;
}
public void performPayment() {
paymentService.pay();
}
}
4.2 使用在不同的位置
- 在字段注入中使用
java
@Component
public class ServiceB {
private final ServiceA serviceA;
@Autowired
public ServiceB(@Qualifier("serviceA1") ServiceA serviceA) {
this.serviceA = serviceA;
}
}
- 在Setter方法注入中使用
java
@Component
public class ServiceB {
private ServiceA serviceA;
@Autowired
public void setServiceA(@Qualifier("serviceA1") ServiceA serviceA) {
this.serviceA = serviceA;
}
}
- 在构造方法中使用
java
@Component
public class ServiceC {
private final ServiceA serviceA;
private final ServiceB serviceB;
@Autowired
public ServiceC(@Qualifier("serviceA1") ServiceA serviceA, ServiceB serviceB) {
this.serviceA = serviceA;
this.serviceB = serviceB;
}
}