Ответ
Поведение зависит от конфигурации:
- Если одна реализация помечена
@Primary— будет выбран этот бин. - Если нет
@Primary, но имя поля совпадает с именем одного из бинов — может быть выбран этот бин (но это поведение не всегда однозначно). - В остальных случаях — Spring выбросит
NoUniqueBeanDefinitionException.
Пример проблемы и решений:
public interface PaymentService {
void process();
}
@Service("cardService")
public class CardPaymentService implements PaymentService { /*...*/ }
@Service("paypalService")
public class PayPalPaymentService implements PaymentService { /*...*/ }
@Component
public class OrderProcessor {
@Autowired // ОШИБКА: NoUniqueBeanDefinitionException
private PaymentService paymentService;
}
Способы разрешения:
- Использование
@Primary:@Service @Primary // Теперь этот бин будет выбран по умолчанию public class CardPaymentService implements PaymentService { /*...*/ } - Использование
@Qualifier(предпочтительно для ясности):@Component public class OrderProcessor { @Autowired @Qualifier("paypalService") // Явно указываем, какую реализацию использовать private PaymentService paymentService; } - Инжекция Map или List всех реализаций:
@Autowired private Map<String, PaymentService> allPaymentServices; // Ключ — имя бина
Ответ 18+ 🔞
Давай разберём эту весёлую ситуацию, когда Спринг смотрит на твой код и начинает чесать репу. Представь: у тебя есть интерфейс, типа PaymentService. А реализаций — две. Или три. Или овердохуища. И ты такой пишешь в классе @Autowired private PaymentService paymentService;.
И тут Спринг, этот хитрожопый фреймворк, останавливается, чешет затылок и говорит: «Бля, чувак, а какую из них тебе сунуть-то? Вот эта платит картой, а эта — через какую-то там палку. Они же разные, ёпта!». И швыряет тебе в лицо исключение NoUniqueBeanDefinitionException. По сути, он орёт: «Я нихуя не понял, выбери сам, мудак!».
Так, а как он вообще решает, что куда пихать? Есть правила, как в подъезде:
- Если одна из твоих реализаций помечена
@Primary— всё, вопрос закрыт. Спринг такой: «А, ну тут главная помечена, значит её и впендюрим». Без вариантов. - Если
@Primaryнет, но имя поля совпадает с именем одного из бинов — тут он может догадаться. Может. Но это как игра в русскую рулетку — поведение не всегда однозначное, лучше на это не рассчитывать. - Во всех остальных случаях — получай свою
NoUniqueBeanDefinitionExceptionпрямо в ебало. Пиздец и точка.
Вот смотри, живой пример, как всё это выглядит в коде:
public interface PaymentService {
void process();
}
@Service("cardService")
public class CardPaymentService implements PaymentService { /*...*/ }
@Service("paypalService")
public class PayPalPaymentService implements PaymentService { /*...*/ }
@Component
public class OrderProcessor {
@Autowired // ОШИБКА: NoUniqueBeanDefinitionException. Спринг в ахуе.
private PaymentService paymentService;
}
Ну и что делать, спросишь ты? Вариантов — как говна за баней.
-
Воткнуть
@Primary(способ для ленивых): Просто помечаешь одну реализацию как главную. Спринг успокаивается и всегда тыкает её.@Service @Primary // Теперь этот бин — царь и бог, его и будут совать везде по умолчанию public class CardPaymentService implements PaymentService { /*...*/ } -
Использовать
@Qualifier(способ для адекватных): Это предпочтительнее, потому что сразу видно, какую именно хуйню ты хочешь. Явно указываешь имя бина.@Component public class OrderProcessor { @Autowired @Qualifier("paypalService") // Чётко говорим: «Давай сюда ту, что через палку, а не карточную!» private PaymentService paymentService; } -
Заинжектить Map или List всех реализаций (способ для извращенцев): А хочешь сразу все? Получи! Spring аккуратно сложит все бины этого типа в коллекцию. В Map ключом будет имя бина.
@Autowired private Map<String, PaymentService> allPaymentServices; // Соберёт всё: и "cardService", и "paypalService" // Потом сам решай, какую из них взять и куда применить.
Короче, суть в том, чтобы не доводить Spring до состояния «терпения ноль ебать». Либо дай ему однозначную команду через @Qualifier, либо назначь главную через @Primary, либо забери всё разом и разбирайся сам. Выбор за тобой, чувак.