@Provides与@Named并不适用于超类型声明的变量

时间:2015-04-20 11:06:35

标签: java guice

我正在探索Guice功能并面临一种奇怪的行为 - 当我将变量声明为

@Inject
@Named("dragon")
Dragon dragon2;

注入按预期工作,但是当我想将dragon2声明为接口(它实现了Creature)时,i。即

@Inject
@Named("dragon")
Creature dragon2;

我收到错误

没有针对@com.google.inject.name.Named(value=dragon)注释的warlock.rincewind.creatures.Creature绑定的实现。

这是我的提供者方法:

@Named("dragon")
@Provides
public Dragon providesDragon() {
    Dragon d = new Dragon("Morkeleb");
    return d;
}

我知道,有很多不同的方法可以克服这个问题(最简单的方法是将更改类型提供给Creature),但我试图找到这种限制的原因。

1 个答案:

答案 0 :(得分:9)

考虑一下,例如:

interface Creature { }

class Dragon implements Creature { }
class Dog implements Creature { }

public class Kennel {
    @Inject @Named("foo") Creature c;
}

public class KennelModule extends Abstract Module {
    @Override
    protected void configure() {
        bind(Dragon.class).annotatedWith(Names.named("foo"));
        bind(Dog.class).annotatedWith(Names.named("foo"));
    }
}

您的注射如何知道是否在此处绑定DragonDog

它不能! 注入密钥不协变。您需要做的是,指定要注入的子类,并将其绑定到您要注入的接口或超类。换句话说:

public class KennelModule extends Abstract Module {
    @Override
    protected void configure() {
        bind(Creature.class).annotatedWith(Names.named("foo").to(Dragon.class);
    }
}

这将为您提供所需的行为。当然,您还可以专门为Dragon绑定注入。