使用Guice

时间:2017-02-19 00:10:55

标签: java dependency-injection guice

对不起,如果这是一个微不足道的问题,我是Guice的新手。 假设我有以下课程:

public class MyClass {
     @Inject
     public MyClass(final MyDependency myDependency) {
          this.name = myDependency.getName();
     }

     public String getName() {
          this.name;
     }
}

然后我想做的其他地方:

public class SomeOtherClass {
    public void test() {
        MyClass instanceFoo = injector.getInstance(MyClass.class);
        MyClass instanceBar = injector.getInstance(MyClass.class);

        assertTrue("foo", instanceFoo.getName());
        assertTrue("bar", instanceBar.getName());
    }
}

我想有两个“MyClass”实例,一个名为“foo”,另一个名称为“bar”(即每个实例都有一个不同的依赖实例)。如何将这两个实例添加到我的注入器中,如何使用“injector.getInstance”检索每个实例?

我不想为每个可能的依赖项创建“MyClass”的子类。

谢谢!

1 个答案:

答案 0 :(得分:5)

您的问题,如标题中所示,有一个更简单的解决方案:如果您想要任意数量的MyClass或MyDependency实例,则可以注入Provider<MyClass>Provider<MyDependency>。无论您是否在模块中实际绑定了提供商,都是如此;对于图中可用的任何T,Guice实际上可以注入TProvider<T>。 (这些分别对应Injector.getInstanceInjector.getProvider。)

正如在问题正文中,有两部分:为同一Key创建多个可注入Class,并以不同的名称和注入的依赖关系设置实例

键和绑定注释

Guice使用Key标识绑定,MyClass是一个完全限定的类(如List<MyClass>BindingAnnotation),并结合可选的&#34;绑定注释&#34;。这是一个注释,它本身用javax.inject.Qualifier@Named注释;您可以创建自己的,也可以使用带有字符串的内置名为@Named("foo")的内容(因此@Named("bar")annotatedWith不同。)

大多数情况下,您可以直接使用Key:在bind调用中使用@Provides或将注释添加到getInstance方法,并通过添加注释来请求它们到构造函数参数或@Inject-annotated字段。但是,您仍然可以使用Key上的静态方法手动创建密钥来使用getProviderNames.named。 (对于复杂的情况,请使用TypeLiteral或@Named("foo") MyClass;有关详细信息,请参阅其文档。)

设置实例

既然您知道如何注入@Foo MyClasstoInstance,那么您如何提供它们?根据您的需要,我选择以下三个选项之一:绑定@Provides,使用bind方法,或创建&#34;辅助注射&#34;工厂。

  • 如果您的MyClass实例不需要自己注入,并且您不会改变或操纵实例状态,那么您可以准备根据需要命名的实例,然后toInstance @Provides @Named("foo") MyClass

  • 您还可以编写MyClass方法,该方法采用toInstance参数(Guice通过注入器提供),设置名称并返回实例。这是编写Provider类或实例的低开销替代方法,它将为您提供一个新的实例,而不是name绑定所暗示的共享。

  • 如果您真的希望MyClass.Factory成为类的构造函数参数的一部分,也许为了保持实例不可变,您可以使用&#34; Assisted Injection&#34;告诉Guice你自己提供哪些参数,哪些来自Guice注射器。这样您就可以注入一个myClassFactory.create("foo")并调用@Provides,您可以直接在您的消费类中使用,或使用上面的public function load($data, $formName = null) { $scope = $formName === null ? $this->formName() : $formName; if($scope) { $data[$scope]['images'] = \yii\helpers\Json::encode($data[$scope]['images']); } else { $data['images'] = \yii\helpers\Json::encode($data['images']); } return parent::load($data, $formName); // TODO: Change the autogenerated stub } 技术。细节有点超出了问题的范围,但查阅&#34;辅助注射&#34;有关语法和添加适当JAR的详细信息。