Переопределить привязку или дочерний модуль в 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();
}
}
}