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 .