我正在使用Google Guice编写一个组件,该组件位于不使用任何依赖注入工具的Web应用程序旁边。
组件中的Guice模块有一些“固定”绑定,这些绑定不会改变,而且一对是动态的,因为它们会在Web应用程序的每个请求中发生变化。
我解决这个问题的简单方法是,每次Web应用程序要求组件第一次执行某些操作时,组件都会构建新的Guice模块,创建实例并将其返回给Web应用程序:
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-覆盖动态绑定(回答https://stackoverflow.com/a/531110/1587864)。这仍然需要创建一个新的注入器,所以我会遇到同样的问题。
2-实现某种已在Injector中绑定的Factory,并且能够访问来自Web应用程序的“动态”属性,并且是按请求进行的。
我不确定如何实现第二个,Guice中是否存在这个概念?
由于
答案 0 :(得分:3)
正如评论所说,完整正确的解决方案是Scope
。假设您已将SimpleScope
的{{1}}实现复制到项目中,那么这就是我在您的组件中所做的事情。如上所述,我假设Foo
和Bar
是您需要基于每个请求创建的对象,X
是您最终需要Guice创建的类的类。我进一步假设X
上有一个名为doTheActualRequestLogic
的方法,它是您希望调用以最终返回到servlet的方法:
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();
}
}
}