Переопределить привязку или дочерний модуль в Guice

Я пишу компонент, используя Google Guice, который находится рядом с веб-приложением, которое не использует какой-либо инструмент для внедрения зависимостей.

Модуль Guice в компоненте имеет несколько "фиксированных" привязок, которые не изменятся, и пару динамических, поскольку они меняются при каждом запросе от веб-приложения.

Простой (и плохой) способ, который я решил, заключается в том, что каждый раз, когда веб-приложение запрашивает компонент сделать что-то в первый раз, компонент создает новый модуль Guice, создает экземпляр и возвращает его в веб-приложение:

public static X init(@NotNull final Foo perRequestObject, @NotNull final Bar perRequestObject2)
{
    final Injector injector = Guice.createInjector(new AbstractModule()
    {
        @Override
        protected void configure()
        {
            install(new NonChanging Module());
            bind(Foo.class).toInstance(perRequestObject);
            bind(Bar.class).toInstance(perRequestObject2);
        }
    });
    return return injector.getInstance(X.class);
}

Я думаю, что это плохой подход, так как сборка Injector за запрос обходится дорого. То, что я хотел бы иметь, является уже созданным инжектором, который я могу переопределить во время выполнения. Я нашел кое-что вокруг:

1- Переопределите динамические привязки (ответ /questions/41002311/pereopredelenie-svyazyivaniya-v-guice/41002329#41002329). Для этого еще нужно создать новый инжектор, чтобы у меня была такая же проблема.

2- Реализовать некую фабрику, которая уже связана в Injector и имеет возможность доступа к "динамическим" свойствам, которые поступают из веб-приложения и предоставляются по запросу.

Я не уверен, как реализовать второй, существует ли эта концепция в Guice?

Спасибо

1 ответ

Решение

Как говорится в комментариях, полное правильное решение Scope, Предполагая, что вы скопировали реализацию SimpleScope из этой статьи в ваш проект, то вот что я буду делать в вашем компоненте. Как вы делаете выше, я предполагаю Foo а также Bar являются ли объекты, которые вам нужны, созданы для каждого запроса, и X это класс того, что вам в конечном итоге нужно, чтобы Guice создал. Я предполагаю далее, что X имеет на это метод, называемый doTheActualRequestLogic это метод, который вы хотите вызвать, чтобы в конечном итоге вернуться к сервлету:

public class MyWebComponent
{
  private final Provider<X> theGuiceCreatedObject;
  private final SimpleScope perRequestScope;

  public MyWebComponent() {
    perRequestScope = new SimpleScope();
    Injector injector = Guice.createInjector(new AbstractModule()
    {
        @Override
        protected void configure()
        {
            install(new NonChangingModule());
            bind(Foo.class).toProvider(SimpleScope.seededKeyProvider())
                .in(perRequestScope);
            bind(Bar.class).toProvider(SimpleScope.seededKeyProvider())
                .in(perRequestScope);
        }
    });
    theGuiceCreatedObject = injector.getProvider(X.class);
  }

  // I assume methods called makeFoo and makeBar that can make
  // a Foo or Bar for a request

  // called by the web service to say "handle this request"
  public RequestResult handleRequest(DataToMakeFooAndBarWith requestData) {
    try {
      perRequestScope.enter();
      perRequestScope.seed(Foo.class, makeFoo(requestData));
      perRequestScope.seed(Bar.class, makeBar(requestData));
      return theGuiceCreatedObject.get().doTheActualRequestLogic(requestData);
    } finally {
      perRequestScope.exit();
    }
  }
}
Другие вопросы по тегам