Sea*_*ter 47 java ioc-container guice typeliteral
我希望能够使用Guice注入通用接口的通用实现.
public interface Repository<T> {
void save(T item);
T get(int id);
}
public MyRepository<T> implements Repository<T> {
@Override
public void save(T item) {
// do saving
return item;
}
@Override
public T get(int id) {
// get item and return
}
}
Run Code Online (Sandbox Code Playgroud)
在C#中使用Castle.Windsor,我可以做到:
Component.For(typeof(Repository<>)).ImplementedBy(typeof(MyRepository<>))
Run Code Online (Sandbox Code Playgroud)
但我不认为Guice中存在等价物.我知道我可以TypeLiteral
在Guice 中使用来注册个人实现,但是有没有办法像Windsor那样一次注册它们?
编辑:
这是一个用法示例:
Injector injector = Guice.createInjector(new MyModule());
Repository<Class1> repo1 = injector.getInstance(new Key<Repository<Class1>>() {});
Repository<Class2> repo2 = injector.getInstance(new Key<Repository<Class2>>() {});
Run Code Online (Sandbox Code Playgroud)
虽然更可能的用法是注入另一个类:
public class ClassThatUsesRepository {
private Repository<Class1> repository;
@Inject
public ClassThatUsesRepository(Repository<Class1> repository) {
this.repository = repository;
}
}
Run Code Online (Sandbox Code Playgroud)
Kde*_*per 65
为了在Guice中使用泛型,您需要使用TypeLiteral类来绑定泛型变体.这是Guice进样器配置的示例:
package your-application.com;
import com.google.inject.AbstractModule;
import com.google.inject.TypeLiteral;
public class MyModule extends AbstractModule {
@Override
protected void configure() {
bind(new TypeLiteral<Repository<Class1>>(){})
.to(new TypeLiteral<MyRepository<Class1>>(){});
}
}
Run Code Online (Sandbox Code Playgroud)
(存储库是通用接口,MyRepository是通用实现,Class1是泛型中使用的特定类).
在运行时没有保留的泛型确实使得首先掌握这个概念变得更加困难.无论如何,有理由new ArrayList<String>().getClass()
返回Class<?>
而不是Class<String>
,虽然将其安全地投射给Class<? extends String>
你应该记住,泛型只是用于编译时类型检查(有点像隐式验证,如果你愿意的话).
因此,如果您想MyRepository
在需要新实例(任何类型)时使用Guice注入(使用任何类型)实现,Repository
那么您根本不必考虑泛型,但是您可以自己确保类型安全(这就是为什么你得到那些讨厌的"未经检查"的警告).
这是一个代码工作得很好的例子:
public class GuiceTest extends AbstractModule {
@Inject
List collection;
public static void main(String[] args) {
GuiceTest app = new GuiceTest();
app.test();
}
public void test(){
Injector injector = Guice.createInjector(new GuiceTest());
injector.injectMembers(this);
List<String> strCollection = collection;
strCollection.add("I'm a String");
System.out.println(collection.get(0));
List<Integer> intCollection = collection;
intCollection.add(new Integer(33));
System.out.println(collection.get(1));
}
@Override
protected void configure() {
bind(List.class).to(LinkedList.class);
}
}
Run Code Online (Sandbox Code Playgroud)
这打印:
I'm a String
33
Run Code Online (Sandbox Code Playgroud)
但该名单是由一个实现LinkedList
.虽然在这个例子中,如果你试图将一个int作为String的东西,你会得到一个例外.
int i = collection.get(0)
Run Code Online (Sandbox Code Playgroud)
但是如果你想获得一个已经类型化的可注入对象,那么你可以要求List<String>
而不仅仅是List,但是然后Guice会将该Type变量视为绑定键的一部分(类似于@Named之类的限定符).这意味着,如果你想注入明确 List<String>
要的ArrayList<String>
实施和List<Integer>
是的LinkedList<Integer>
,吉斯让你这样做(未测试,猜测).
但有一个问题:
@Override
protected void configure() {
bind(List<String>.class).to(LinkedList<String>.class); <-- *Not Happening*
}
Run Code Online (Sandbox Code Playgroud)
您可能会注意到类文字不是通用的.这就是你使用Guice的地方TypeLiterals
.
@Override
protected void configure() {
bind(new TypeLiteral<List<String>>(){}).to(new TypeLiteral<LinkedList<String>>(){});
}
Run Code Online (Sandbox Code Playgroud)
TypeLiterals
保留泛型类型变量作为元信息的一部分以映射到所需的实现.希望这可以帮助.
归档时间: |
|
查看次数: |
27029 次 |
最近记录: |