在Guice中覆盖绑定或子模块

时间:2014-07-02 08:33:49

标签: java guice guice-3

我正在使用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中是否存在这个概念?

由于

1 个答案:

答案 0 :(得分:3)

正如评论所说,完整正确的解决方案是Scope。假设您已将SimpleScope的{​​{1}}实现复制到项目中,那么这就是我在您的组件中所做的事情。如上所述,我假设FooBar是您需要基于每个请求创建的对象,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();
    }
  }
}