【问题标题】:Override binding or child module in Guice覆盖 Guice 中的绑定或子模块
【发布时间】:2014-07-02 08:33:48
【问题描述】:

我正在使用 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 中的工厂,并且能够访问来自 Web 应用程序且按请求提供的“动态”属性。

不知道第二个怎么实现,Guice 有这个概念吗?

谢谢

【问题讨论】:

  • Modules.override 是否满足您的要求?
  • 这正是@RequestScoped 的用途。查看guice-servlet 文档。
  • @TavianBarnes RequestScoped 需要一个我无法获得的请求。我的案例将更关注线程范围而不是请求。有什么想法吗?
  • Guice wiki 在自定义范围上有一个article,它显示了一个示例线程特定范围。

标签: java guice guice-3


【解决方案1】:

正如 cmets 所说,完全正确的解决方案是 Scope。假设您已将 SimpleScope 的实现从 this article 复制到您的项目中,那么这就是我将在您的组件中执行的操作。正如您在上面所做的那样,我假设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();
    }
  }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-04-09
    • 2017-05-31
    • 2017-03-25
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多