【问题标题】:Guice - Inject object with two different implementationsGuice - 用两种不同的实现注入对象
【发布时间】:2019-03-05 23:21:54
【问题描述】:

首先我不得不说我尝试在谷歌上搜索这个问题的答案,但没有答案解释我的疑问。 反正, 我想了解的是以下内容:

public interface Animal{
 public void makeSound(int times);
}

这个接口有两种不同的实现:

public class Cat implements Animal{
 @Override
 public void makeSound(int times){
   for(int=0;i<times;i++){ 
      this.meow();
   }
 }
}

public class Dog implements Animal{
 @Override
 public void makeSound(int times){
   for(int=0;i<times;i++){ 
      this.wolf();
   }
  }
}

我将使用这些实现,如下例所示:

public class AnimalStateManager {

 @Inject
 private Animal animal;

 public void makeAnimalAct(){
   animal.makeSound(100)
 }

}

更新 1.1 到帖子

我还有一个使用相同“动物”界面的课程:

 public class AnimalMakeSoundOnce {

     @Inject
     private Animal animal;

     public void makeSoundOnce(){
       animal.makeSound(1)
     }

    }

所以我的问题是: 1- 我如何知道要注入 AnimalStateManager 的实现是什么? 2- 如果我想强制“AnimalStateManager”上的“动物”对象成为猫怎么办?

更新 1.1 到帖子 3- 如果我想让 AnimalMakeSoundOnce 使用 Dog 实现而 AnimalStateManager 使用 Cat 实现怎么办?

提前致谢

【问题讨论】:

    标签: java oop dependency-injection guice


    【解决方案1】:

    在 Guice 中,您必须实现一个模块(覆盖 AbstractModule 类)并将 Animal 绑定到特定的实现类。 回答您的问题:

    1. 您当然可以调用animal.getClass() 在运行时检查注入了哪个实现类。但这会打破 IOC 的原则,即无论您使用哪种具体实现都无关紧要。

    2. 要强制 animal 在您的 AnimalStateManager 中成为猫,您必须编写自己的模块。

      public class AnimalStateModule extends AbstractModule {
      
          @Override
          protected void configure() {
              bind(Animal.class).to(Cat.class);
          }
      }
      

    然后实例化 AnimalState:

    Injector inj = Guice.createInjector(new AnimalStateModule());
    final AnimalStateManager ass = inj.getInstance(AnimalStateManager.class);
    ass.makeAnimalAct(); // will cause a call to Cat.meow()
    

    【讨论】:

    • 您好,感谢您的明确回答,您能看看我在帖子上所做的更新,并告诉您是否有帮助吗? 10x
    【解决方案2】:

    我认为另一个重要的问题是您将如何同时使用 MakeSound 和 MakeSoundOnce 对象。在上面创建的同一个模块中,有多种方法可以指定您想要的类型,这两种方法都是绑定注释的方法(https://github.com/google/guice/wiki/BindingAnnotations):

    1) 您可以使用 Guice 提供的 @Named 注解。您会得到如下所示的内容:

    @Override
    protected void configure() {
        bind(Animal.class).annotatedWith(Names.named("Cat")).to(Cat.class);
        bind(Animal.class).annotatedWith(Names.named("Dog")).to(Dog.class);
    }
    

    然后将用于:

    @Inject @Named("Cat") private Animal animal;
    

    在您的 *MakeSound 类中。

    2) 您还可以创建自己的注释(在上面的同一链接中进行了非常详细的描述),您可以选择使用:

    @Inject @Cat private Animal animal;
    

    在您的 *MakeSound 类中。大多数时候我们坚持使用@Named 注解,因为它不需要创建额外的注解接口。

    *MakeSound 类会通过注入实现吗?您是否需要在您描述的 *MakeSound 类中切换 Dog/Cat 实现(即,希望猫只喵一次,反之亦然)?

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-05-13
      • 2014-07-25
      • 2013-07-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-10-03
      相关资源
      最近更新 更多