Оригинальное название: Как декларативно настроить несколько bean-компонентов для одного и того же интерфейса и выбрать правильный во время выполнения
В последнее время у меня был проект, для которого требовалось следующее веб-приложение:быть реализовано:
Когда пользователь входит в систему, он указывает область действия (B2C, B2B).Пока она работает с приложением, некоторые вызовы бэкэнд-систем должны перенаправляться в разные экземпляры бэкэнд-систем в зависимости от области текущего входа в систему.
Веб-приложение состоит из двух частей (SPA спереди, SpringЗагрузочное приложение с конечными точками REST в конце) и набор экземпляров внутренних систем, например, архив для B2C и один архив для B2B.
Текущая реализация обрабатывает запросы REST и определяет объемвойдите в какой архив звонить.Это работает, но я хочу сделать это декларативным вместо явного кодирования.Так что должно быть легко добавить новый экземпляр для другой области видимости.
Для начала я бы хотел определить два компонента: один для доступа к архиву B2C и один для доступа к архиву B2B.Оба будут реализовывать один и тот же интерфейс;на самом деле они являются экземплярами одного и того же класса с разными значениями конфигурации.
Когда обрабатывается вызов REST, я бы хотел, чтобы spring выбрала правильный bean-компонент, который будет вызываться, исходя из объема текущего входа в систему (B2C илиB2B).
У меня были разные идеи, как решить эту проблему (прокси Scoped, AOP, custom AutowireCandidateResolver
, Object Pools), но в настоящее время я застрял и не могу сказать, нахожусь ли я на правильном путиВот.
Кто-нибудь уже сделал что-то подобное?
Обновление
Благодарю Фрица Дюшарда и Кена Бекова за идеюиспользуйте Factories + Scoped Proxies и верните их в вызывающий код.
Обновление 2
Я только что реализовал расширение Spring, способное выполнить следующий тест (полный код здесь: https://gitlab.com/thuri/service-provider-proxy).
Внутренние классы предназначены только для продолжения теставместе. Это также должно работать, когда они находятся в отдельных файлах.
Суть в том, что Интерфейс реализован двумя разными bean-компонентами, и во время выполнения Spring решает, какой bean-компонент должен обрабатывать вызов, оценивая выражение spEL.в аннотациях
@Test
public void testProxiedResourceInjectionWithField() {
caseSwitch.switchValue = "B2B";
assertEquals("Well you know ... ", client.proxiedService.doCoolStuff());
caseSwitch.switchValue = "B2C";
assertEquals("This will do ...", client.proxiedService.doCoolStuff());
}
public static class ProxiedServiceClient {
@Autowired
public ProxiedServiceInterface proxiedService;
}
@ServiceProviderProxy
public static interface ProxiedServiceInterface {
public String doCoolStuff();
}
@ProxiedService(expression = "#{switch.switchValue == 'B2B'}")
public static class B2BServiceImpl implements ProxiedServiceInterface {
@Override
public String doCoolStuff() {
return "Well you know ... ";
}
}
@ProxiedService(expression = "#{switch.switchValue == 'B2C'}")
public static class B2CServiceImpl implements ProxiedServiceInterface {
@Override
public String doCoolStuff() {
return "This will do ...";
}
}
public static class CaseSwitch {
public String switchValue = "";
}