Рубрики
Без рубрики

Аннотация квалификатора Spring @

Одного только @Autowired иногда недостаточно, чтобы устранить неоднозначность зависимостей. Вы можете более точно использовать аннотацию @Qualifier. @Primary также может помочь.

Автор оригинала: baeldung.

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 .