Bindings: 注入する物を定義する
ここで説明するのは Bindingsに関して三種類
- Linked Bindings
- Instance Bindings
- Binding Annotation
Linked Bindings
Moduleの configureの中で bind(Interface.class).to(Concrete.class); とやる事で Interfaceへ注入するべき実装が Concrete.classである事を宣言する
public class GreetingModule extends AbstractModule {
@Override
protected void configure() {
bind(SayHelloInterface.class).to(Konnitiwa.class);
bind(SayGoodbyeInterface.class).to(Sayonara.class);
}
}
Instance Bindings
toInstance()を使って Instanceを直接 Bind
@Inject @Named("URL")
String site_url;
bind(Sting.class).annotatedWith(Names.named("URL")).toInstance("https://www.google.com/");
あまり良い例じゃないか。
こうする事で Stringの Fieldが@Inject @Named(“URL”)とAnnotationされているときに、InjectorによってURL文字列が注入されます。
Injectorのインスタンス作成時間に影響するらしいので、インスタンス作成に時間のかかるオブジェクトをtoInstanceで注入するのは やめておけというのがドキュメントにかかれてます。
Binding Annotation
同じインターフェースに対して異なる 実装を Bindingしたい場合
public class Client {
@Inject
private Service normalService;
@Inject
private Service specialService;
public Client() {
}
}
annotatedWithで条件を付けてやる
public class Client {
@Inject
private Service normalService;
@Inject @Named("Special")
private Service specialService;
public Client() {
}
}
bindの仕方は以下のような形
// 特に条件無し
bind(Service.class).to(ServiceImpl.class);
// 条件付き
bind(Service.class).annotatedWith(Names.named("Special")).to(ServiceImplSpecial.class);
としてやれば、それぞれ Module側の指定にしたがって適切にInjectされる。
@Namedによる Bindingは文字列なので簡単に間違える。アノテーションを独自に実装する事でコンパイル時チェックが効くようになる。
以下は @Special というアノテーションの実装
import com.google.inject.BindingAnnotation;
import java.lang.annotation.Target;
import java.lang.annotation.Retention;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
import static java.lang.annotation.ElementType.PARAMETER;
import static java.lang.annotation.ElementType.FIELD;
import static java.lang.annotation.ElementType.METHOD;
@BindingAnnotation
@Target({ FIELD, PARAMETER, METHOD })
@Retention(RUNTIME)
public @interface Special {}
クライアント側
@Inject @Special
private Service specialService;
Module側
bind(Service.class).to(ServiceImpl.class);
bind(Service.class).annotatedWith(Special.class).to(ServiceImplSpecial.class);