Revision 1 as of 2009-12-12 06:22:45

Clear message
Locked History Actions

guice/Manual/FAQ

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を使ってファクトリのボイラープレートコードを削除することを考慮してください。

二つの同じような、しかし少しだけ違うオブジェクトツリーを作成するにはどうしたらいいですか?

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.

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:

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"));
          }
        });
  }

See also Alen Vrecko's more complete example.

内部クラスに注入する方法は?

Guice doesn't support this. However, you can inject a nested class (sometimes called a "static inner class"):

class Outer {

  • static class Nested {
    • ..
    }

}

ジェネリック型を持つクラスに注入するには?

You may need to inject a class with a parameterized type, like List<String>:

class Example {
  @Inject
  void setList(List<String> list) {
    ...
  }
}

You need to use TypeLiteral to create the binding. TypeLiteral is a special class that allows you to specify a full parameterized type.

  @Override public void configure() {
    bind(new TypeLiteral<List<String>>() {}).toInstance(new ArrayList<String>());
  }

オプショナルなパラメータをコンストラクタに注入するには?

Neither constructors nor @Provides methods support optional injection. To work-around this, you can create an inner class that holds the optional value:

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();
  }
}

This also allows for a default value for the optional parameter.

メソッドインターセプタを注入するには?

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);
  }
}

他の質問に答えてもらうには?

Please post to the google-guice discussion group.