2016-03-15 53 views
1

我的课程取决于一些服务需要少量参数然后进行网络调用,目前我正在传递这些参数,然后通过注入我的课堂的工厂创建这些服务。我需要将这些服务作为依赖注入,我知道我可以为它们创建提供程序,但在大多数示例中,我发现提供程序通常会绑定到像serveraddres等固定值,但我需要在此期间给出值运行。如何使用自定义参数配置提供者?

下面是我的示例代码:

public SomeClass { 
    private final SomeFactory someFactory; 

    @Inject 
    SomeClass(SomeFactory factory) { 
     someFactory = factory; 
    } 

    public Foo getFoo(String fooId) { 
     FooService fooService = someFactory.getFooService(fooId); 
     return fooService.getFoo(); 
    } 

} 

我需要做的是:

public SomeClass { 
    private final FooService fooService; 

    @Inject 
    SomeClass(FooService fooService) { 
     this.fooService = fooService; 
    } 

    public Foo getFoo(String fooId) { 
     return fooService.getFoo(); 
    } 

} 

更新1

使用情况更加清晰:

@Provides 
    @RequestScoped 
    public SomeService provideSomeService(Dep1 dep1, String code) throws IOException { 
    return new SomeService.Builder() 
     .withApplicationName("Foo") 
     .setCode(code) 
     .build(); 
    } 

在这里,code可以是null默认情况下,当需要时我可以给它一些价值。

我可以以某种方式在提供程序创建之前将参数传递给提供程序吗?

+1

你可以做到这一点只有在'code'可以注射:静态(因为一些配置),或通过一些提供者(在你的情况下,因为'代码'是恒定的,但与会话范围有关) –

+0

@JérémieB如果我们在同一页面上,那么我们不能在Guice中用动态值做任何事情在这种情况下,我需要重组我的应用程序,对吧? – vivek

回答

1

如果你有你的价值绑定(这里,code是一个没有绑定注释的字符串),那么你的更新1正是代码的样子。

在实践中,有一些差异:

  • 常数像intString值通常与结合注解,无论@Named或自定义注释。
  • 如果您需要在Guice初始化后将值注入到对象图中,但具有足够深的对象图,依赖注入仍然是一个好主意,则可以创建一个child injector。通过这种方式,您可以在一个操作或对象中访问@Named("code") String,但不能跨越整个Guice应用程序。
  • 如果您的code的值足够动态以至于无法通过Guice作为自己的关键字提供,那么您必须通过使用某种工厂来传递它。对于一个基于Builder的对象,我会说你的SomeFactory实现是我想出的最好的。

如果您不需要使用Builder,并且可以让Guice根据您的字段或构造函数参数创建对象,则可以通过代码生成Factory。

  • Guice可以通过FactoryModuleBuilder为您生成一个工厂,其功能名为"assisted injection"
  • 谷歌的其他工具,AutoFactory,将代码生成一个在Guice和Dagger中工作的工厂实现。 (它是捆绑为“自动”,其中包括一个名为AutoValue模型对象发生器,还生成注释实现。)

我把孩子喷射器的小规模示威活动,并在my other SO answer here辅助注射。

+0

按需要我的意思是运行时间我可以改变代码的价值,但我认为这不是一个好主意。我认为guice只适用于静态依赖。 – vivek

0

这里最好的办法是参数化模块,并通过一个供应商,你在运行时创建的参数:

public class MyModule extends AbstractModule { 
    private final String code; 

    public MyModule(String code) { 
    this.code = code; 
    } 

    @Override public void configure() { 
    Provider<Dep1> depProvider = getProvider(Dep1.class); 
    bind(SomeService.class) 
     .toProvider(() -> new SomeService.Builder() 
      .withApplicationName("Foo") 
      .withDep(depProvider.get()) 
      .setCode(code) 
      .build()) 
     .in(RequestScoped.class); 
    } 
} 
+0

此代码在模块初始化期间正在设置,因此我们无法在运行时重置代码。 – vivek

+0

好吧,无论如何字符串是不可改变的,所以它们在运行时不能改变。也许传入'AtomicReference '并依赖于它,在运行时更改它?我想说这是一个很大的反模式,而不是Guice应该如何使用。考虑让那些依赖于不断变化的字符串的东西调用一些其他服务来获得它的当前值。 – Cardano

+0

假设依赖图中有一个服务可以根据http请求等参数具有不同的行为,那么你可以用guice做到这一点吗? – vivek

相关问题