Как Spring autowire по имени, когда найдено более одного соответствия bean?
Предположим, что у меня есть такие интерфейсы, как:
interface Country {}
class USA implements Country {}
class UK implements Country ()
И этот фрагмент конфигурации xml:
<bean class="USA"/>
<bean id="country" class="UK"/>
<bean id="main" class="Main"/>
Как я могу контролировать, какая из зависимостей автоподключена ниже? Я бы хотел, чтобы Великобритания.
class Main {
private Country country;
@Autowired
public void setCountry(Country country) {
this.country = country;
}
}
Я использую Spring 3.0.3.RELEASE.
Ответы
Ответ 1
Это описано в в разделе 3.9.3 руководства Spring 3.0:
Для ответного соответствия имя bean считается значением классификатора по умолчанию.
Другими словами, поведение по умолчанию, как если бы вы добавили @Qualifier("country")
в метод setter.
Ответ 2
Вы можете использовать аннотацию @Qualifier
От здесь
Тонкая настройка автонастройки на основе аннотаций с квалификаторами
Так как автосогласование по типу может приводить к нескольким кандидатам, часто необходимо иметь больший контроль над процессом выбора. Один из способов добиться этого - аннотация Spring @Qualifier. Это позволяет связать значения квалификатора с конкретными аргументами, сужая набор совпадений типа, чтобы для каждого аргумента был выбран конкретный bean. В простейшем случае это может быть простое описательное значение:
class Main {
private Country country;
@Autowired
@Qualifier("country")
public void setCountry(Country country) {
this.country = country;
}
}
Это будет использовать Великобританию, добавив идентификатор в США bean и использовать это, если вы хотите США.
Ответ 3
Другим способом достижения такого же результата является использование аннотации @Value:
public class Main {
private Country country;
@Autowired
public void setCountry(@Value("#{country}") Country country) {
this.country = country;
}
}
В этом случае строка "#{country}
представляет собой выражение Spring выражение (SpEL), которое оценивается как bean с именем country
.
Ответ 4
Еще одно решение с разрешением по имени:
@Resource(name="country")
Он использует пакет javax.annotation, поэтому не имеет значения Spring, но Spring поддерживает его.
Ответ 5
В некоторых случаях вы можете использовать аннотацию @Primary.
@Primary
class USA implements Country {}
Таким образом, он будет выбран в качестве автозапуска автозапуска по умолчанию, при этом нет необходимости использовать autowire-кандидат на другом bean.
для mo deatils посмотрите Autowiring два beans, реализующие один и тот же интерфейс - как установить по умолчанию bean для автоустройства?