Анотация на пролетта @Qualifier

1. Общ преглед

В тази статия ще проучим с какво може да ни помогне анотацията @Qualifier , кои проблеми решава и как да я използваме.

Също така ще обясним как се различава от анотацията @Primary и от автоматичното свързване по име.

2. Необходимост от автоматично свързване на кабели за двузначност

В @Autowired анотацията е чудесен начин за печелене на необходимостта да се придаде на зависимостта през пролетта изрично. И въпреки че е полезно, има случаи на използване, за които само тази анотация не е достатъчна за Spring, за да разбере кой боб да инжектира.

По подразбиране Spring разрешава автоматично свързани кабели по тип.

Ако в контейнера са налични повече от един боб от същия тип, рамката ще изхвърли NoUniqueBeanDefinitionException , което показва, че има повече от един боб на разположение за автоматично свързване.

Нека си представим ситуация, при която съществуват два възможни кандидата за Spring, които да инжектират като сътрудници на боб в даден случай:

@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; }

Ако се опитаме да заредим FooService в нашия контекст, рамката Spring ще хвърли NoUniqueBeanDefinitionException . Това е така, защото Spring не знае кой боб да инжектира . За да избегнете този проблем, има няколко решения. В @Qualifier анотацията е един от тях.

3. Анотация на квалификатора

Използвайки анотацията @Qualifier , можем да премахнем проблема кой зърно трябва да се инжектира .

Нека да прегледаме предишния си пример и да видим как решаваме проблема, като включим анотацията @Qualifier, за да посочим кой боб искаме да използваме:

public class FooService { @Autowired @Qualifier("fooFormatter") private Formatter formatter; }

Чрез включването на анотацията @Qualifier заедно с името на конкретната реализация, която искаме да използваме - в този пример Foo - можем да избегнем двусмислието, когато Spring намери множество бобчета от същия тип.

Трябва да вземем предвид, че името на квалификатора, което ще се използва, е това, декларирано в анотацията @Component .

Имайте предвид, че бихме могли да използваме и анотацията @Qualifier в класовете за изпълнение на Formatter , вместо да посочваме имената в техните анотации @Component , за да получим същия ефект:

@Component @Qualifier("fooFormatter") public class FooFormatter implements Formatter { //... } @Component @Qualifier("barFormatter") public class BarFormatter implements Formatter { //... } 

4. @Qualifier срещу @Primary

Има още една анотация, наречена @Primary, която можем да използваме, за да решим кой боб да инжектираме, когато има неяснота по отношение на инжектирането на зависимост.

Тази анотация определя предпочитание, когато присъстват множество зърна от един и същи тип . Бобът, свързан с анотацията @Primary, ще се използва, освен ако не е посочено друго.

Да видим пример:

@Configuration public class Config { @Bean public Employee johnEmployee() { return new Employee("John"); } @Bean @Primary public Employee tonyEmployee() { return new Employee("Tony"); } }

В този пример и двата метода връщат един и същи тип служител . Бобът, който Spring ще инжектира, е този, върнат от метода tonyEfficiee . Това е така, защото съдържа анотацията @Primary . Тази анотация е полезна, когато искаме да посочим кой боб от определен тип трябва да се инжектира по подразбиране .

И в случай, че се нуждаем от другия боб в някаква точка на инжектиране, ще трябва да го посочим специално. Можем да направим това чрез анотацията @Qualifier . Например, бихме могли да уточним, че искаме да използваме боб, върнат от метода johnEfficiee , като използваме анотацията @Qualifier .

Струва си да се отбележи, че ако присъстват както анотациите @Qualifier, така и @Primary , тогава анотацията @Qualifier ще има предимство. По принцип @Primary определя по подразбиране, докато @Qualifier е много специфичен.

Нека да видим друг начин за използване на анотацията @Primary , този път като използваме първоначалния пример:

@Component @Primary public class FooFormatter implements Formatter { //... } @Component public class BarFormatter implements Formatter { //... } 

В този случай анотацията @Primary се поставя в един от изпълняващите класове и ще разграничи сценария.

5. @Qualifier срещу Autowiring по име

Друг начин да решите между множество зърна при автоматично свързване е като използвате името на полето за инжектиране. Това е по подразбиране, в случай че няма други подсказки за пролетта . Нека да видим някакъв код, базиран на нашия първоначален пример:

public class FooService { @Autowired private Formatter fooFormatter; }

В този случай Spring ще определи, че бобът за инжектиране е FooFormatter, тъй като името на полето е съпоставено със стойността, която използвахме в анотацията @Component за този боб.

6. Заключение

Описахме сценариите, при които трябва да различим кои зърна да инжектираме. По-специално, описахме анотацията @Qualifier и я сравнихме с други подобни начини за определяне кои зърна трябва да се използват.

Както обикновено, пълният код за тази статия е достъпен в GitHub.