1. Обзор
В этой статье мы рассмотрим , что может помочь нам с аннотацией , какие проблемы она решает и как ее использовать.
Дальнейшее чтение:
Весна @Основная аннотация
Проводка весной: @Autowired, @Resource и @Inject
Аннотация @Lookup весной
Мы также объясним, чем он отличается от аннотации @Primary и от автозапуска по имени.
2. Необходимость автоматического подключения для устранения неоднозначности
Аннотация @Autowired – отличный способ сделать необходимость введения зависимости в Spring явной. И хотя это полезно, есть случаи использования, для которых одной этой аннотации недостаточно, чтобы Spring понял, какой компонент вводить.
По умолчанию Spring разрешает записи autowired по типу.
Если в контейнере доступно более одного компонента одного и того же типа, фреймворк выдаст исключение NoUniqueBeanDefinitionException , , указывающее, что для автопроводки доступно более одного компонента.
Давайте представим ситуацию, в которой существуют два возможных кандидата на то, чтобы Spring ввел в качестве сотрудников bean в данном случае:
@Component("fooFormatter")
public class FooFormatter implements Formatter {
public String format() {
return "foo";
}
}
@Component("barFormatter")
public class BarFormatter implements Formatter {
public String format() {
return "bar";
}
}
@Component
public class FooService {
@Autowired
private Formatter formatter;
}Если мы попытаемся загрузить Food service в наш контекст, фреймворк Spring выдаст исключение NoUniqueBeanDefinitionException . Это происходит потому, что Spring не знает, какой боб вводить . Чтобы избежать этой проблемы, существует несколько решений. Аннотация @Квалификатор является одной из них.
3. Аннотация @Квалификатора
Используя @квалификатор аннотацию, мы можем устранить проблему, в которую необходимо ввести боб .
Давайте вернемся к нашему предыдущему примеру и посмотрим, как мы решаем проблему, включая аннотацию @Qualifier , чтобы указать, какой компонент мы хотим использовать:
public class FooService {
@Autowired
@Qualifier("fooFormatter")
private Formatter formatter;
}Включив аннотацию @квалификатора вместе с именем конкретной реализации, которую мы хотим использовать – в этом примере Foo – мы можем избежать двусмысленности, когда Spring находит несколько бобов одного и того же типа.
Мы должны принять во внимание, что имя квалификатора, которое будет использоваться, является именем, объявленным в аннотации @Component .
Обратите внимание, что мы могли бы также использовать @Квалификатор аннотацию на Форматере реализующих классах, вместо указания имен в их @Компоненте аннотациях, чтобы получить тот же эффект:
@Component
@Qualifier("fooFormatter")
public class FooFormatter implements Formatter {
//...
}
@Component
@Qualifier("barFormatter")
public class BarFormatter implements Formatter {
//...
}
4. @Квалификатор против @Первичный
Есть еще одна аннотация под названием @Primary, которую мы можем использовать, чтобы решить, какой компонент вводить, когда присутствует двусмысленность в отношении внедрения зависимостей.
Эта аннотация определяет предпочтение, когда присутствует несколько бобов одного типа . Боб, связанный с аннотацией @Primary , будет использоваться, если не указано иное.
Давайте рассмотрим пример:
@Configuration
public class Config {
@Bean
public Employee johnEmployee() {
return new Employee("John");
}
@Bean
@Primary
public Employee tonyEmployee() {
return new Employee("Tony");
}
}В этом примере оба метода возвращают один и тот же тип Employee . Боб, который введет Spring, будет возвращен методом tonyEmployee . Это связано с тем, что он содержит аннотацию @Primary . Эта аннотация полезна, когда мы хотим указать, какой компонент определенного типа должен быть введен по умолчанию .
И в случае, если нам потребуется другой боб в какой-то точке инъекции, нам нужно будет специально указать его. Мы можем сделать это с помощью аннотации @Qualifier . Например, мы могли бы указать, что мы хотим использовать компонент, возвращаемый методом john Employee , используя аннотацию @Qualifier .
Стоит отметить, что если присутствуют как @Квалификатор , так и @Основные аннотации, то @Квалификатор аннотации будут иметь приоритет. В принципе, @Primary определяет значение по умолчанию, в то время как @Квалификатор очень специфичен.
Давайте рассмотрим другой способ использования аннотации @Primary , на этот раз используя исходный пример:
@Component
@Primary
public class FooFormatter implements Formatter {
//...
}
@Component
public class BarFormatter implements Formatter {
//...
}
В этом случае аннотация @Primary помещается в один из реализующих классов и устраняет неоднозначность сценария.
5. @Квалификатор против автозапуска по имени
Другой способ выбрать между несколькими бобами при автопроводке-использовать имя поля для ввода. Это значение по умолчанию, если нет других подсказок для Spring . Давайте рассмотрим некоторый код, основанный на нашем первоначальном примере:
public class FooService {
@Autowired
private Formatter fooFormatter;
}В этом случае Spring определит, что вводимый компонент является FooFormatter , поскольку имя поля соответствует значению, которое мы использовали в аннотации @Component для этого компонента.
6. Заключение
Мы описали сценарии, в которых нам нужно решить, какие бобы вводить. В частности, мы описали аннотацию @Qualifier и сравнили ее с другими аналогичными способами определения того, какие бобы необходимо использовать.
Как обычно, полный код этой статьи доступен на GitHub .