2010-04-05 36 views
25

我正尝试移植一个小项目,用Guice替换一些工厂(这是我第一次Guice试验)。然而,当我试图注入泛型时,我被卡住了。我设法提取与两个阶级,一个模块一个小玩具例子:Guice注入仿制药

import com.google.inject.Inject; 

public class Console<T> { 
    private final StringOutput<T> out; 
    @Inject 
    public Console(StringOutput<T> out) { 
    this.out = out; 
    } 
    public void print(T t) { 
    System.out.println(out.converter(t)); 
    } 
} 

public class StringOutput<T> { 
    public String converter(T t) { 
    return t.toString(); 
    } 
} 

import com.google.inject.AbstractModule; 
import com.google.inject.Guice; 
import com.google.inject.Injector; 
import com.google.inject.TypeLiteral; 


public class MyModule extends AbstractModule { 

    @Override 
    protected void configure() { 
    bind(StringOutput.class); 
    bind(Console.class); 
    } 

    public static void main(String[] args) { 
    Injector injector = Guice.createInjector(new MyModule()); 
    StringOutput<Integer> out = injector.getInstance(StringOutput.class); 
    System.out.println(out.converter(12)); 
    Console<Double> cons = injector.getInstance(Console.class); 
    cons.print(123.0); 
    } 

} 

当我运行这个例子,我的一切是:

在线程异常“主要” com.google.inject.CreationException :Guice创建错误:

1) playground.StringOutput<T> cannot be used as a key; It is not fully specified. 
    at playground.MyModule.configure(MyModule.java:15) 

1 error 
    at com.google.inject.internal.Errors.throwCreationExceptionIfErrorsExist(Errors.java:354) 
    at com.google.inject.InjectorBuilder.initializeStatically(InjectorBuilder.java:152) 
    at com.google.inject.InjectorBuilder.build(InjectorBuilder.java:105) 
    at com.google.inject.Guice.createInjector(Guice.java:92) 

我试图寻找错误消息,但没有找到任何有用的提示。进一步在Guice常见问题解答中,我偶然发现了一个关于如何注射仿制药的问题。我尝试添加以下绑定在configure方法:

bind(new TypeLiteral<StringOutput<Double>>() {}).toInstance(new StringOutput<Double>()); 

但没有成功(同样的错误消息)。

有人可以解释我的错误信息,并提供一些提示吗?谢谢。

回答

27

我认为你看到的具体问题可能是因为bind(Console.class)声明。它也应该使用TypeLiteral。或者,你可以只绑定那些和JIT绑定将为你照顾它,因为这里涉及的两个类型都是具体的类。

另外,你应该检索Console有:

Console<Double> cons = 
    injector.getInstance(Key.get(new TypeLiteral<Console<Double>>(){})); 

编辑:您不必仅仅因为你使用的是TypeLiteral绑定到一个实例。你可以这样做:

bind(new TypeLiteral<Console<Double>>(){}); 

当然,就像我说的上面,你可以使用直接跳过,在这种情况下,并检索从喷射器Console一个Key基础上,TypeLiteral和结合将是隐含的。

+0

谢谢。我不知道如何将TypeLitteral绑定到控制台,因为我无法创建没有StringOutput实例的控制台实例。你能详细说明吗? – paradigmatic

+0

看我的编辑...你不需要使用toInstance()。 – ColinD

+0

我刚试过。它只适用于我定义类型litterals和y使用密钥来获取实例。所以我无法做出明确的约束。 – paradigmatic