Как Spring разрешает неоднозначность при инъекции, если интерфейс имеет несколько реализаций?

«Как Spring разрешает неоднозначность при инъекции, если интерфейс имеет несколько реализаций?» — вопрос из категории Spring, который задают на 10% собеседований Java Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

При наличии нескольких бинов, реализующих один интерфейс, Spring по умолчанию выбрасывает NoUniqueBeanDefinitionException. Для разрешения неоднозначности используются аннотации:

1. @Qualifier — явное указание имени бина:

@Autowired
@Qualifier("smsService") // Внедряет бин с именем "smsService"
private NotificationService service;

@Component("smsService")
public class SmsService implements NotificationService { ... }

@Component("emailService")
public class EmailService implements NotificationService { ... }

2. @Primary — назначение реализации по умолчанию:

@Primary
@Component
public class PrimaryService implements MyInterface { ... } // Будет выбран по умолчанию

@Component
public class SecondaryService implements MyInterface { ... }

3. @Resource (JSR-250) — инъекция по имени:

@Resource(name = "specificBeanName")
private MyInterface bean;

Выбор метода зависит от необходимости гибкости (@Qualifier) или простоты (@Primary).