Deletions are marked like this. | Additions are marked like this. |
Line 78: | Line 78: |
This is commonly called the "robot legs" problem: How to create a robot with a two Leg objects, the left one injected with a LeftFoot, and the right one with a RightFoot. But only one Leg class that's reused in both contexts. | これは一般にrobot legs問題といわれるものです。ロボットを生成するとして、左足はLeftFootを注入し、右足にはRightGootを注入したいとします。しかし、二つのコンテキスト内ではただ一つのLegクラスしか使えないものとします。 |
Line 80: | Line 80: |
There's a PrivateModules solution. It uses two separate private modules, a @Left one and an @Right one. Each has a binding for the unannotated Foot.class and Leg.class, and exposes a binding for the annotated Leg.class: |
PrivateModulesというソリューションがあります。二つの分離したプライベートモジュールを使用します、一つは@Left、もう一つは@Rightです。 それぞれはアノテーションされていないFoot.classとLeg.classを用います。 そして、アノテーションされたLeg.classのみを公開します。 |
Line 113: | Line 115: |
See also Alen Vrecko's more complete example. | [[http://pastie.org/368348|Alen Vreckoの完全な例]]を参照してください。 |
Line 117: | Line 119: |
Guice doesn't support this. However, you can inject a nested class (sometimes called a "static inner class"): |
Guiceではサポートしていませんが、ネストされたクラス(static inner class)に注入することはできます。 {{{ |
Line 124: | Line 126: |
}}} | |
Line 127: | Line 130: |
You may need to inject a class with a parameterized type, like List<String>: | パラメトライズ型のクラスを注入したい場合があると思います。List<String>のような。 |
Line 136: | Line 139: |
You need to use TypeLiteral to create the binding. TypeLiteral is a special class that allows you to specify a full parameterized type. | バインディングを作成するには、TypeLiteralを使う必要があります。TypeLiteralは完全なパラメトライズタイプを指定するための特別なクラスです。 |
Line 145: | Line 148: |
Neither constructors nor @Provides methods support optional injection. To work-around this, you can create an inner class that holds the optional value: |
コンストラクタも@Providesメソッドもオプショナルインジェクションをサポートしていません。 なんとかするには、オプショナルな値を保持する内部クラスを作成することです。 |
Line 162: | Line 166: |
This also allows for a default value for the optional parameter. | これによって、デフォルト値を指定することもできます。 |
Line 166: | Line 170: |
Line 180: | Line 185: |
Please post to the google-guice discussion group. | google-guiceディスカッショングループにポストしてください。 |
Frequently Asked Questions
コンフィギュレーションパラメータはどのように注入すればよいのですか?
あなた自身のパラメータであることを識別させるためのバインディングアノテーションが必要です。 パラメータを定義するアノテーションを作成します。
/** * Annotates the URL of the foo server. */ @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.FIELD, ElementType.PARAMETER}) @BindingAnnotation public @interface FooServerAddress {}
このアノテーションをモジュール内で値にバインドします。
public class FooModule { private final String fooServerAddress; /** * @param fooServerAddress fooサーバのURL */ public FooModule(String fooServerAddress) { this.fooServerAddress = fooServerAddress; } @Override public void configure() { bindConstant().annotatedWith(FooServerAddress.class).to(fooServerAddress); ... } }
最後にクラスに注入します。
public class FooClient { @Inject FooClient(@FooServerAddress String fooServerAddress) { ... }
ビルトインの@Namedバインディングアノテーションを使うと、少々キーストロークを減らすことができるかもしれません。
コンフィギュレーションプロパティはどのようにロードすればよいのですか?
コンフィギュレーションファイル内のそれぞれのプロパティについて、nmaes.bindProperties()を使ってバインディングを作成してください。
Guice経由で作成したオブジェクトにどのようにパラメータを渡せばいいのですか?
注入される値として直接的にパラメータを渡すことはできません。 ただし、Guicewo使ってファクトリを作成し、そのファクトリを呼び出してオブジェクトを作成することはできます。
public class Thing { // 注意:ここでは@Injectアノテーションは使わない 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) { ... } }
AssistedInjectを使ってファクトリのボイラープレートコードを削除することを考慮してください。
二つの同じような、しかし少しだけ違うオブジェクトツリーを作成するにはどうしたらいいですか?
これは一般にrobot legs問題といわれるものです。ロボットを生成するとして、左足はLeftFootを注入し、右足にはRightGootを注入したいとします。しかし、二つのコンテキスト内ではただ一つのLegクラスしか使えないものとします。
PrivateModulesというソリューションがあります。二つの分離したプライベートモジュールを使用します、一つは@Left、もう一つは@Rightです。 それぞれはアノテーションされていないFoot.classとLeg.classを用います。 そして、アノテーションされたLeg.classのみを公開します。
class LegModule extends PrivateModule { private final Class<? extends Annotation> annotation; LegModule(Class<? extends Annotation> annotation) { this.annotation = annotation; } @Override protected void configure() { bind(Leg.class).annotatedWith(annotation).to(Leg.class); expose(Leg.class).annotatedWith(annotation); bindFoot(); } abstract void bindFoot(); } public static void main(String[] args) { Injector injector = Guice.createInjector( new LegModule(Left.class) { @Override void bindFoot() { bind(Foot.class).toInstance(new Foot("leftie")); } }, new LegModule(Right.class) { @Override void bindFoot() { bind(Foot.class).toInstance(new Foot("righty")); } }); }
Alen Vreckoの完全な例を参照してください。
内部クラスに注入する方法は?
Guiceではサポートしていませんが、ネストされたクラス(static inner class)に注入することはできます。
class Outer { static class Nested { ... } }
ジェネリック型を持つクラスに注入するには?
パラメトライズ型のクラスを注入したい場合があると思います。List<String>のような。
class Example { @Inject void setList(List<String> list) { ... } }
バインディングを作成するには、TypeLiteralを使う必要があります。TypeLiteralは完全なパラメトライズタイプを指定するための特別なクラスです。
@Override public void configure() { bind(new TypeLiteral<List<String>>() {}).toInstance(new ArrayList<String>()); }
オプショナルなパラメータをコンストラクタに注入するには?
コンストラクタも@Providesメソッドもオプショナルインジェクションをサポートしていません。 なんとかするには、オプショナルな値を保持する内部クラスを作成することです。
class Car { private final Engine engine; private final AirConditioner airConditioner; @Inject public Car(Engine engine, AirConditionerHolder airConditionerHolder) { this.engine = engine; this.airConditioner = airConditionerHolder.value; } static class AirConditionerHolder { @Inject(optional=true) AirConditioner value = new NoOpAirconditioner(); } }
これによって、デフォルト値を指定することもできます。
メソッドインターセプタを注入するには?
In order to inject dependencies in an AOP MethodInterceptor, use requestInjection() alongside the standard bindInterceptor() call.
public class NotOnWeekendsModule extends AbstractModule { protected void configure() { MethodInterceptor interceptor = new WeekendBlocker(); requestInjection(interceptor); bindInterceptor(any(), annotatedWith(NotOnWeekends.class), interceptor); } }
他の質問に答えてもらうには?
google-guiceディスカッショングループにポストしてください。