Как выбрать Spring Bean для вызова во время выполнения - PullRequest
0 голосов
/ 09 февраля 2019

Оригинальное название: Как декларативно настроить несколько 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 = "";
  }

1 Ответ

0 голосов
/ 09 февраля 2019

Это может быть сделано для работы с Spring Factory Bean , для которого было установлено область запроса или сеанса , например:

@Bean(name = "archive")
@Scope(value= "request", proxyMode = ScopedProxyMode.TARGET_CLASS)
public ArchiveFactory archiveFactory() {
    ArchiveFactory factory = new ArchiveFactory();
    return factory;
}

Spring будет использоватьAOP Proxies для создания новых bean-компонентов во время выполнения, например, при каждом запросе, используя реализацию фабричного bean-компонента.Вы можете использовать локальный поток для передачи текущего контекста.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...