【问题标题】:how to pass both injected and assisted parameters to a Guice Provider?如何将注入参数和辅助参数传递给 Guice Provider?
【发布时间】:2013-02-26 14:57:03
【问题描述】:

我有以下提供者:

  public class GuiceResourceProvider implements Provider<WebResource> {

    @Inject
    private Configuration configuration;
    @Inject
    private Environment environment;

    private String name;

    @Inject
    public GuiceResourceProvider(@Assisted("name") String name) {
        this.name = name;
    }

    @Override
    public WebResource get() {
        if (name == "default") {
            String connectionsDSResourceUrl = "http://localhost:" + this.configuration.getHttpConfiguration().getPort();
            Client connectionsDSHttpClient = new JerseyClientBuilder().using(this.configuration.getHttpClientConfiguration()).using(this.environment).build();
            connectionsDSHttpClient.addFilter(new RequestIdClientFilter());
            return connectionsDSHttpClient.resource(connectionsDSResourceUrl);
        } else if(name == "other"){
            return ......
        }
    }
}

我需要创建这个 Provider 的 2 个实例,一个将绑定一个带有“default”注释的 WebResource 注入,一个将绑定一个带有“other”注释的 WebResource 注入。

让Guice创建Provider实例如下:

    bind(WebResource.class).annotatedWith(Names.named("default")).toProvider(GuiceResourceProvider.class).in(Scopes.SINGLETON);
bind(WebResource.class).annotatedWith(Names.named("other")).toProvider(GuiceResourceProvider.class).in(Scopes.SINGLETON);

注入参数没问题,但我无法提供自定义参数。如果我尝试手动实例化一个实例并提供自定义参数,那么注入的当然有问题。如果我遵循辅助符号,问题是我需要在模块中注入提供者的工厂,当然,这完全关闭了!

谁能帮忙?

【问题讨论】:

  • 不确定name == "default"是否会给你想要的结果。

标签: guice


【解决方案1】:

对于可能感兴趣的每个人,我都找到了答案。 如果要将注入的和自定义的参数都传递给提供者,请将注入的参数从构造函数移动到字段并使用构造函数传递您自己的参数。绑定时,首先创建 Provider 的实例,将参数传递给构造函数,然后在此实例上调用 requestInjection 以将其添加到注入图中,然后将您的类绑定到 Provider 实例,如下所示:

GuiceResourceProvider guiceResourceProvider = new GuiceResourceProvider("default");
requestInjection(guiceResourceProvider);

bind(WebResource.class).annotatedWith(Names.named("default")).toProvider(guiceResourceProvider).in(Scopes.SINGLETON);

这是提供者:

public class GuiceResourceProvider implements Provider<WebResource> {

@Inject
private Configuration configuration;
@Inject
private Environment environment;

private String name;

@Inject
public GuiceResourceProvider(String name) {
    this.name = name;
}

@Override
public WebResource get() {
    if (name == "default") {
        String connectionsDSResourceUrl = "http://localhost:" + this.configuration.getHttpConfiguration().getPort();
        Client connectionsDSHttpClient = new JerseyClientBuilder().using(this.configuration.getHttpClientConfiguration()).using(this.environment).build();
        connectionsDSHttpClient.addFilter(new RequestIdClientFilter());
        return connectionsDSHttpClient.resource(connectionsDSResourceUrl);
    } else if(name == "other"){
        return ......
    }
}

}

【讨论】:

  • 请记住,“辅助注射”往往是指在注射时接受参数,而不是在配置时。这是重构通用 Provider 以提供配置时已知的有限密钥集的合理解决方案。
  • 是的,这是真的。尽管如此,我还是找到了一些参考资料(书中也有一份),指出如果要将参数传递给 Provider,可以使用 Assisted 表示法。但没有提供示例。
【解决方案2】:

这里有一些问题:

  • 不要将字符串与== 进行比较,将它们与equals 进行比较。 == 按引用进行比较,但两者可能是对相等字符串的不同实例的引用。
  • Provider 是一个零参数工厂。如果您有工厂,则不需要 Provider。
  • 辅助注入与@Named 等绑定注解是不同的系统。绑定注释只是查找提供程序的映射键的一半(Class 或 TypeLiteral 是另一半)。辅助注入允许您在注入时获取一个或多个参数,并自动连接一个为您执行此操作的接口。如果您在单个工厂方法中接受多个相同的参数类型,则辅助注入参数仅采用 @Assisted("foo") 注释;否则 Guice 可以弄清楚。
  • 没有很好的方法可以从您要注入的依赖项中读取绑定注释中的参数值 - 但由于具有不同参数值的绑定注释彼此不相等,因此可以单独绑定每个注释。

我认为您的逻辑在 @Provides 方法中看起来最好:

public class WebResourceModule extends AbstractModule {

  @Override public void configure() { }

  @Provides @Named("default") @Singleton WebResource makeDefaultResource(
      Configuration configuration, Environment environment) {
    String connectionsDSResourceUrl = "http://localhost:" + this.configuration.getHttpConfiguration().getPort();
    Client connectionsDSHttpClient = new JerseyClientBuilder().using(this.configuration.getHttpClientConfiguration()).using(this.environment).build();
    connectionsDSHttpClient.addFilter(new RequestIdClientFilter());
    return connectionsDSHttpClient.resource(connectionsDSResourceUrl);
  }

  @Provides @Named("other") @Singleton WebResource makeOtherResource(
      YourDependencies here) {
    return somethingElse();
  }
}

但是如果你想使用自定义工厂逻辑的 any 字符串,只需创建一个不实现 Provider 的单方法可注入类,并使用它来创建和返回任何 @987654329 @你喜欢。

【讨论】:

  • 感谢您的宝贵时间,但您的回答根本没有帮助。你本质上说“不要试图让事情变得复杂,只是因为你似乎不明白它是如何工作的”。好吧,事实并非如此。我知道我可以使用@provides 方法,事实上,这是我的第一个版本,效果很好。但是现在,我正在尝试重构,因为我需要根据条件以编程方式创建提供程序和相关绑定。当然,这不能通过提供方法的特殊语法来完成。
  • 这根本不是我要说的。我很抱歉,如果它被认为是居高临下的——只要简单的东西还不够,复杂的解决方案就可以了。我确实支持我针对上述问题提出的解决方案,以及@Assisted("name") 永远无法访问@Named 注释的声明,但是由于您在编译时通过您的参数,将您的密钥绑定到一个通用 Provider 的实例是有意义的。
猜你喜欢
  • 1970-01-01
  • 2016-04-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-11-30
  • 2013-09-01
  • 1970-01-01
相关资源
最近更新 更多