一个不完整的 FAQ 介绍如何使用Guice1.0去做一些事情
推荐的方式是自己为每一个参数写一个注解:
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD, ElementType.PARAMETER})
@BindingAnnotation
public @interface Greeting {}
@Inject
Foo(@Greeting String greeting) { ... }
bindConstant().annotatedWith(Greeting.class).to("Hello!");
如果你不想为每一个参数都写一个注解那么可以这样使用@Named注解:
@Inject
Foo(@Named("greeting") String greeting) { ... }
bindConstant().annotatedWith(Names.named("greeting")).to("Hello!");
这样需要更少的代码,但是如果你拼写错误,编译器不会帮你找出来.另一个方式是写一个配置类,为每一个参数写一个get方法,但这样导致很困难去真正告诉每一个类应该用哪一个参数。
Guice 1.0 不提供这样的功能,但是你可以写一个自己的module去读取配置文件然后绑定这些参数。
比较高级的使用注解和module的方法是将配置配置文件的读取从参数的注入的功能中分离出来,这样就可以在不需要改变大多数代码的情况下,更改从什么地方读取配置文件。
Guice并没有在1.0中直接提供这样的方法,但你可以自己写一个工场方法或者使用AssistedInject.当你写工场方法的时候,可以将工场由Guice进行创建,而需要的对象由工场创建,而不是由Guice创建。
public class Thing {
// note: no @Inject annotation here
private Thing(A a, B b) {
...
}
public static class Factory {
@Inject
public Factory(A a) { ... }
public Thing make(B b) { ... }
}
}
public class Example {
@Inject
public Example(Thing.Factory factory) { ... }
}
目前你需要分别注入。
Guice不支持注入内部类,但是你可以注入一个嵌套类 (有时被称为静态内部类):
class Outer {
static class Nested {
...
}
}
Guice 1.0 不支持这样做. 但你可以使用另外的一个可选的属性
class Example {
@Inject(optional=true)
void setFoo(String value) { ... }
}
如果你根本没有绑定参数,它不会被注入
不幸的是,这种方式仅适用于常量(比如String),不是你自定义的类。
Guice未来将支持Null,另外一个选择是使用 null object .
如果你需要像这样注入范形:
class Example {
@Inject
void setList(List<String> list) { ... }
}
你可能会想到这样来绑定:
bind(List.class).toInstance(new ArrayList<String>());
实际上你会得到下面的错误: com.google.inject.CreationException?: Guice configuration errors: Binding to java.util.List<java.lang.String> not found. No bindings to that type were found.
这样来绑定它就可以工作了: