Это автоматически определяется с @Autowired? Это внедрение зависимостей по имени, когда используется @Qualifier? Как мы можем сделать инъекцию сеттера и конструктора, используя эти аннотации?
Spring @Autowired и @Qualifier
Ответ 1
Вы можете использовать @Qualifier
вместе с @Autowired
. Фактически, Spring попросит вас явно выбрать компонент, если обнаружен неоднозначный тип компонента, и в этом случае вы должны предоставить квалификатор
.Например, в следующем случае необходимо предоставить квалификатор
@Component
@Qualifier("staff")
public Staff implements Person {}
@Component
@Qualifier("employee")
public Manager implements Person {}
@Component
public Payroll {
private Person person;
@Autowired
public Payroll(@Qualifier("employee") Person person){
this.person = person;
}
}
EDIT:
В Lombok 1.18.4, наконец, можно избежать шаблона при внедрении конструктора, когда у вас есть @Qualifier, поэтому теперь можно сделать следующее:
@Component
@Qualifier("staff")
public Staff implements Person {}
@Component
@Qualifier("employee")
public Manager implements Person {}
@Component
@RequiredArgsConstructor
public Payroll {
@Qualifier("employee") private final Person person;
}
при условии, что вы используете новое правило lombok.config copyableAnnotations из правила lombok (поместив следующее в lombok.config в корне вашего проекта):
# Copy the Qualifier annotation from the instance variables to the constructor
# see https://github.com/rzwitserloot/lombok/issues/745
lombok.copyableAnnotations += org.springframework.beans.factory.annotation.Qualifier
Это было недавно введено в последней версии lombok 1.18.4.
- сообщение в блоге, где подробно обсуждается проблема
- оригинальный выпуск на github
- И небольшой проект GitHub, чтобы увидеть его в действии
Примечание
Если вы используете инъекцию поля или сеттера, тогда вы должны поместить @Autowired и @Qualifier поверх функции поля или сеттера, как показано ниже (любой из них будет работать)
public Payroll {
@Autowired @Qualifier("employee") private final Person person;
}
или
public Payroll {
private final Person person;
@Autowired
@Qualifier("employee")
public void setPerson(Person person) {
this.person = person;
}
}
Если вы используете инъекцию конструктора, аннотации должны быть помещены в конструктор, иначе код не будет работать. Используйте его, как показано ниже -
public Payroll {
private Person person;
@Autowired
public Payroll(@Qualifier("employee") Person person){
this.person = person;
}
}
Ответ 2
Аннотация @Qualifier
используется для разрешения конфликта автопроводки, когда существует несколько бинов одного типа.
Аннотация @Qualifier
может использоваться для любого класса, аннотированного @Component
или для методов, аннотированных @Bean
. Эта аннотация также может применяться к аргументам конструктора или параметрам метода.
Пример: -
public interface Vehicle {
public void start();
public void stop();
}
Существует два компонента: Car и Bike реализуют интерфейс автомобиля.
@Component(value="car")
public class Car implements Vehicle {
@Override
public void start() {
System.out.println("Car started");
}
@Override
public void stop() {
System.out.println("Car stopped");
}
}
@Component(value="bike")
public class Bike implements Vehicle {
@Override
public void start() {
System.out.println("Bike started");
}
@Override
public void stop() {
System.out.println("Bike stopped");
}
}
Внедрение компонента Bike Bean в VehicleService с использованием @Autowired
с аннотацией @Qualifier
. Если вы не использовали @Qualifier
, он выдаст исключение NoUniqueBeanDefinitionException.
@Component
public class VehicleService {
@Autowired
@Qualifier("bike")
private Vehicle vehicle;
public void service() {
vehicle.start();
vehicle.stop();
}
}
Ссылка: - пример аннотации @Qualifier
Ответ 3
@Autowired
для автоматического подключения (или поиска) по типу @Qualifier
для автоматического подключения (или поиска) по имени
Другой альтернативный вариант для @Qualifier
- @Primary
@Component
@Qualifier("beanname")
public class A{}
public class B{
//Constructor
@Autowired
public B(@Qualifier("beanname")A a){...} // you need to add @autowire also
//property
@Autowired
@Qualifier("beanname")
private A a;
}
//If you don't want to add the two annotations, we can use @Resource
public class B{
//property
@Resource(name="beanname")
private A a;
//Importing properties is very similar
@Value("${property.name}") //@Value know how to interpret ${}
private String name;
}
больше о @value