【问题标题】:Guice: How to use an instance instead of a Provider when I already have the instanceGuice:当我已经拥有实例时如何使用实例而不是提供者
【发布时间】:2014-02-12 20:23:30
【问题描述】:

在之前的项目中使用 Guice 3.0 之后,我在新项目中使用 Guice 4.0 Beta 2。

在我当前的项目中,有一个 ApplicationConfiguration 对象,它是使用 ApplicationConfigurationProvider 从 HTTP 请求派生的:

  @Inject
  public ApplicationConfigurationProvider(HttpServletRequest request)
  {
    this.request = request;
  }

  @Override
  public ApplicationConfiguration get()
  {
    ApplicationConfiguration app = null;

    Map<String, ApplicationConfiguration> appMap = 
            (Map<String, ApplicationConfiguration>) request.getSession()
            .getServletContext()
            .getAttribute(ContextKeys.APPLICATION_CONFIGURATIONS.toString());

    //get the host.....
    String host = request.getServerName();
    if(host.equals("localhost"))
    {
      app = appMap.get("abcclient");
    }
    else
    {
      app = appMap.get("xyzclient");
    }

    return app;
  }

绑定如下所示:

bind(ApplicationConfiguration.class).toProvider(ApplicationConfigurationProvider.class).in(RequestScoped.class);

到目前为止一切顺利。这按预期工作。请注意,其他 Provider 类依赖于将 ApplicationConfiguration 注入其中。

这是我遇到问题的地方:我需要进行一些批处理。批处理过程不是由 HTTP 请求启动的。我有正确的ApplicationConfiguration 实例可用(它不需要通过使用HTTP 请求来选择),但我不知道如何绑定它,或者告诉Injector 使用这个实例而不是ApplicationConfigurationProvider

我想我可以创建一个自定义范围并使用我想用于该范围的 ApplicationConfiguration 实例为其播种,但它不起作用。我使用 Guice wiki 上的示例创建了自定义范围。

我以为我可以在自定义范围内将ApplicationConfiguration 绑定到其他类型的Provider,但这也不起作用,因为 Guice 只允许绑定一个特定的键一次。

总之,我需要将ApplicationConfiguration 绑定到我在“批处理”模式下已经拥有的特定实例(当我在请求之外使用它时),并在 HTTP 请求中使用ApplicationConfiguratoniProvider .我希望如果我有ApplicationConfiguration 实例,将注入它的其他提供者将像现在一样工作(在 HTTP 请求中时)。

我该怎么做?

谢谢!!!!

-瑞恩

【问题讨论】:

  • 你知道在注入器创建时你是否处于“批处理”模式吗?
  • 我可以。我想现在我的计划是使用子注入器,每个 ApplicationConfiguration 实例一个。父注入器将使用所有“标准”绑定,而子注入器将使用特定于 ApplicationConfiguration 的绑定。因此,在 HTTP 请求中,我将只选择正确的注入器,而不是使用 Provider 来选择正确的 ApplicationConfiguration。在批处理模式下,我只会选择正确的注射器。听起来可行吗?
  • 不,父注入器中的对象无法从子注入器获取依赖项。但是有一个解决方案,我会把它作为答案。

标签: guice


【解决方案1】:

有很多方法可以解决这个问题。如果您知道应用程序在启动时是处于“批处理”模式还是普通模式,您可以这样做:

@Override
public void configure() {
    if (isInBatchMode) {
        bind(ApplicationConfiguration.class)
                .toInstance(batchInstance);
    } else {
        bind(ApplicationConfiguration.class)
                .toProvider(ApplicationConfigurationProvider.class)
                .in(RequestScoped.class);
    }
}

其中isInBatchModebatchInstance 被传递到Module。或者您可以根据配置等制作两个不同的模块并安装不同的模块。

如果您在 HTTP 请求中,您还可以编写一个自定义提供程序,该提供程序从请求中返回实例,否则返回“批处理”实例。您可以使用自定义过滤器检查您是否在 HTTP 请求中。

【讨论】:

    【解决方案2】:

    好的,我想通了。

    我真正想做的是在 HTTP 请求之外重用 RequestScope,但我认为这并不容易。事实证明,ServletScopes.scopeRequest 方法正是我所需要的。

    Guice 论坛上的这条评论实际上让我走上了正确的道路:

    https://groups.google.com/d/msg/google-guice/ozexD9etcXI/40kbz1PDdIEJ

    我用注入器绑定中定义的少数请求范围变量为seedMap 播种,如图所示创建了Callable,它工作了!

    这里是 JavaDoc,它说 scopeRequest 方法正是我想要它做的事情:

    http://google-guice.googlecode.com/svn/trunk/javadoc/com/google/inject/servlet/ServletScopes.html

    感谢大家的帮助!!

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-08-16
      • 1970-01-01
      • 2012-05-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多