Ответ 1
Предполагая, что у вас уже есть сотни интерфейсов и реализаций (как вы сказали в комментарии), и вы не хотите реорганизовывать весь код... тогда это сложная проблема... и это сложное решение:
Вы можете создать пользовательский BeanDefinitionRegistryPostProcessor
и реализовать либо метод postProcessBeanDefinitionRegistry
, либо postProcessBeanFactory
.
Таким образом, у вас есть доступ ко всем определениям bean, прежде чем они будут созданы и введены. Сделайте свою логику, чтобы найти, какая предпочтительная реализация для каждого из ваших интерфейсов, а затем установите ее как первичную.
@Component
public class CustomBeanDefinitionRegistryPostProcessor implements BeanDefinitionRegistryPostProcessor {
@Override
public void postProcessBeanDefinitionRegistry(
BeanDefinitionRegistry registry) throws BeansException {
// this method can be used to set a primary bean, although
// beans defined in a @Configuration class will not be avalable here.
}
@Override
public void postProcessBeanFactory(
ConfigurableListableBeanFactory beanFactory) throws BeansException {
// here, all beans are available including those defined by @configuration, @component, xml, etc.
// do some magic to somehow find which is the preferred bean name for each interface
// you have access to all bean-definition names with: beanFactory.getBeanDefinitionNames()
String beanName = "aImpl2"; // let say is this one
// get the definition for that bean and set it as primary
beanFactory.getBeanDefinition(beanName).setPrimary(true)
}
}
Жесткая часть - найти имя bean, это зависит от специфики вашего приложения. Я предполагаю, что использование согласованного соглашения об именах поможет.
Update:
Кажется, что оба метода в интерфейсе BeanDefinitionRegistryPostProcessor
могут использоваться для этой цели. Имея в виду, что в фазе postProcessBeanDefinitionRegistry
beans, сконфигурированный с помощью классов @configuration, пока недоступен, как отмечено в комментариях ниже.
С другой стороны, они действительно доступны в postProcessBeanFactory
.