Ответ
Когда Spring находит несколько бинов, подходящих для инъекции, возникает неоднозначность. Её можно разрешить несколькими способами.
Основные методы:
-
Аннотация
@Qualifier: Прямое указание имени конкретного бина.@Component("firstService") public class FirstServiceImpl implements MyService {} @Component("secondService") public class SecondServiceImpl implements MyService {} @Service public class ClientService { @Autowired @Qualifier("secondService") // Явно указываем, какой бин внедрить private MyService service; } -
Аннотация
@Primary: Помечает один из кандидатов как бин по умолчанию.@Component @Primary // Этот бин будет выбран, если нет других указаний public class PrimaryServiceImpl implements MyService {} @Component public class SecondaryServiceImpl implements MyService {} -
Имя поля/параметра: Если имя поля совпадает с именем одного из бинов (при использовании
@Autowired).@Component public class MyServiceImpl implements MyService {} @Service public class ClientService { @Autowired private MyService myServiceImpl; // Будет внедрен бин с именем 'myServiceImpl' } -
Кастомная аннотация: Создание своей аннотации, мета-аннотированной
@Qualifier.@Target({ElementType.FIELD, ElementType.PARAMETER, ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) @Qualifier public @interface DatabaseType { String value(); } @Component @DatabaseType("mysql") public class MySqlService implements DataService {} @Service public class BusinessService { @Autowired @DatabaseType("mysql") private DataService dataService; }
Ответ 18+ 🔞
А, ну это же классика, ёпта! Вечный геморрой, когда Spring, как слепой котёнок, тычется носом в несколько одинаковых бинов и не знает, какой ему впендюрить. "No qualifying bean of type... available: expected single matching bean but found 2". Знакомо, сука? Чувствуешь, как волнение ебать начинает подкатывать?
Ну ладно, не кипятись. Есть несколько проверенных способов этого распиздяйства избежать. Смотри сюда.
Основные методы, чтобы не было мути:
-
Аннотация
@Qualifier— твой прямой указатель, блядь. Ты просто берёшь и говоришь: "Эй, дурачок, не тупи, вот конкретно этот бин мне и тащи". Как палецем тычешь.@Component("firstService") public class FirstServiceImpl implements MyService {} @Component("secondService") public class SecondServiceImpl implements MyService {} @Service public class ClientService { @Autowired @Qualifier("secondService") // Смотри сюда, мудак! Бери того, который 'secondService'! private MyService service; } -
Аннотация
@Primary— это типа "любимчик". Один бин получает корону, и его всегда выбирают первым, если других указаний нет. Удобно, но опасненько, если забыть, кто тут главный.@Component @Primary // Этот парень — царь и бог. Его и тащи по умолчанию, если не сказано иначе. public class PrimaryServiceImpl implements MyService {} @Component public class SecondaryServiceImpl implements MyService {} // Этот будет сидеть и курить в сторонке. -
Имя поля/параметра — магия, на которую лучше не рассчитывать. Если ты назовёшь поле так же, как называется один из бинов, Spring иногда догадается. Но это, блядь, как ходить по тонкому льду — вроде работает, а потом раз — и пиздец, не работает.
@Component public class MyServiceImpl implements MyService {} // Бин зовут 'myServiceImpl' @Service public class ClientService { @Autowired private MyService myServiceImpl; // Опа-на! Имя совпало! Может, пронесёт... } -
Кастомная аннотация — для пафосных и умных. Когда обычный
@Qualifierтебе кажется слишком простым, ты создаёшь свою собственную, блядь, аннотацию. Выглядит охуенно солидно, хотя по сути — та же самая хуйня, но в профиль.@Target({ElementType.FIELD, ElementType.PARAMETER, ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) @Qualifier // Главное — не забыть эту приписку, а то будет пизда. public @interface DatabaseType { String value(); } @Component @DatabaseType("mysql") public class MySqlService implements DataService {} @Service public class BusinessService { @Autowired @DatabaseType("mysql") // Во, теперь ясно — только MySQL, никаких этих ваших Postgres'ов! private DataService dataService; }
Вот и вся наука, блядь. Выбирай, что душе угодно. Главное — не оставляй Spring'а в подвешенном состоянии, а то он тебе такую неоднозначность устроит, что мало не покажется. В рот меня чих-пых!