Guice-使用两种不同的实现注入对象

时间:2019-03-04 16:51:45

标签: java oop dependency-injection guice

首先,我不得不说我曾尝试谷歌搜索该问题的答案,但没有答案能解释我的疑问。 无论如何, 我想了解的是以下内容:

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实现怎么办?

预先感谢

2 个答案:

答案 0 :(得分: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()

答案 1 :(得分:0)

我认为另一个重要的问题是您将如何同时使用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注释,因为它不需要创建额外的Annotation接口。

* MakeSound类将通过Injection实现吗?并且您是否需要在您描述的* MakeSound类中切换Dog / Cat实现(即,只让猫喵喵一次,反之亦然)?