Guice - 用两种不同的实现注入对象
Guice - Inject object with two different implementations
首先我不得不说我尝试用谷歌搜索这个问题的答案,但没有答案解释我的疑虑。
反正,
我想了解的是以下内容:
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 到 POST
我还有一个 class 使用相同的 "Animal" 界面:
public class AnimalMakeSoundOnce {
@Inject
private Animal animal;
public void makeSoundOnce(){
animal.makeSound(1)
}
}
所以我的问题是:
1- 我怎么知道要将什么实现注入到 AnimalStateManager 中?
2- 如果我想强制 "AnimalStateManager" 上的 "animal" 对象成为猫怎么办?
更新 1.1 到 POST
3- 如果我想让 AnimalMakeSoundOnce 使用 Dog 实现而 AnimalStateManager 使用 Cat 实现怎么办?
提前致谢
在 Guice 中,您必须实现一个模块(覆盖 AbstractModule
class)并将 Animal 绑定到特定实现 class。
回答您的问题:
您当然可以调用 animal.getClass()
以在运行时检查注入了哪个实现 class。但这会破坏 IOC 的原则,无论您使用哪种具体实现都无关紧要。
要在您的 AnimalStateManager
中强制 animal
be cat,您必须编写自己的模块。
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()
我认为另一个重要的问题是您将如何同时使用 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) 您还可以创建自己的注释(在上面的相同 link 中有非常详细的描述),这将使您可以选择使用:
@Inject @Cat private Animal animal;
在您的 *MakeSound 类 中。大多数时候我们坚持使用@Named 注解,因为它不需要创建额外的注解接口。
*MakeSound 类 会通过注入实现吗?您是否需要在您描述的 *MakeSound 类 中切换 Dog/Cat 实现(即,想让一只猫只喵喵叫一次,反之亦然)?
首先我不得不说我尝试用谷歌搜索这个问题的答案,但没有答案解释我的疑虑。 反正, 我想了解的是以下内容:
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 到 POST
我还有一个 class 使用相同的 "Animal" 界面:
public class AnimalMakeSoundOnce {
@Inject
private Animal animal;
public void makeSoundOnce(){
animal.makeSound(1)
}
}
所以我的问题是: 1- 我怎么知道要将什么实现注入到 AnimalStateManager 中? 2- 如果我想强制 "AnimalStateManager" 上的 "animal" 对象成为猫怎么办?
更新 1.1 到 POST 3- 如果我想让 AnimalMakeSoundOnce 使用 Dog 实现而 AnimalStateManager 使用 Cat 实现怎么办?
提前致谢
在 Guice 中,您必须实现一个模块(覆盖 AbstractModule
class)并将 Animal 绑定到特定实现 class。
回答您的问题:
您当然可以调用
animal.getClass()
以在运行时检查注入了哪个实现 class。但这会破坏 IOC 的原则,无论您使用哪种具体实现都无关紧要。要在您的
AnimalStateManager
中强制animal
be cat,您必须编写自己的模块。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()
我认为另一个重要的问题是您将如何同时使用 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) 您还可以创建自己的注释(在上面的相同 link 中有非常详细的描述),这将使您可以选择使用:
@Inject @Cat private Animal animal;
在您的 *MakeSound 类 中。大多数时候我们坚持使用@Named 注解,因为它不需要创建额外的注解接口。
*MakeSound 类 会通过注入实现吗?您是否需要在您描述的 *MakeSound 类 中切换 Dog/Cat 实现(即,想让一只猫只喵喵叫一次,反之亦然)?