web-dev-qa-db-ja.com

Guiceを使用してコンストラクターにパラメーターを渡す

私は次のような工場を持っています、

public final class Application {

    private static IFoo foo;

    public static IFoo getFoo(String bar)
    {
        // i need to inject bar to the constructor of Foo
        // obvious i have to do something, not sure what
        Injector injector = Guice.createInjector();
        logger = injector.getInstance(Foo.class);
        return logger;              
    }

}

これはFooの定義です。

class Foo
{
   Foo(String bar)
   {

   }

}

OK。 Guiceを使用してこのパラメーターをFooコンストラクターに渡す方法がわかりませんか?

何か案は?

31
DarthVader

「Guice Constructor Parameter」の回答はすべて、何らかの形で不完全なようです。使用方法を含む完全なソリューションを次に示します。

interface FooInterface{
  String getFooName();
}

//コンストラクターに注釈を付け、実装クラスのパラメーターを補助しました

class Foo implements FooInterface {
   String bar;

   @Inject
   Foo(@Assisted String bar)
   {
      this.bar = bar;
   }

   // return the final name
   getFooName(){
     return this.bar;
   }

}

//アシストされたパラメータのみを受け取るcreate()メソッドを使用して、ファクトリインターフェイスを作成します。

// FooFactoryインターフェースには明示的な実装クラスはありません(Guice Magic)

interface FooFactory{
   Foo create(String bar);
}

// AssistedInjectによって作成されたプロバイダーにそのファクトリをバインドします

binderModule implements Module{

 void configure(Binder binder) {
   binder.install(new FactoryModuleBuilder()
         .implement(FooInterface.class, Foo.class)
         .build(FooFactory.class));
 }
}

//ここで使用します:

class FooAction{

   @Inject private FooFactory fooFactory;

   doFoo(){
      // Send bar details through the Factory, not the "injector" 
      Foo f = fooFactory.create("This foo is named bar. How lovely!");
      f.getFooName(); // "This foo is named bar. How lovely!"
   }
}

多くのヘルプ: https://google.github.io/guice/api-docs/latest/javadoc/index.html?com/google/inject/assistedinject/FactoryModuleBuilder.html

52
DougA

これは古いスレッドであることは知っていますが、今日は自分で問題を見つけました。 「Foo」のインスタンスは2つまたは最大3つだけ必要であり、Factoryのすべての定型コードを記述したくはありませんでした。少しグーグルで見つけました Stubbisms – Tony’s Weblog 必要なインスタンスを正確に知っていれば完璧なこのソリューションをお勧めします。

Guiceモジュールで:

    bind(Foo.class).annotatedWith(Names.named("firstFoo")).toProvider(new Provider<Foo>() {
        @Override
        public Foo get() {
            return new FooImpl("topic A");
        }
    });
    bind(Foo.class).annotatedWith(Names.named("secondFoo")).toProvider(new Provider<Foo>() {
        @Override
        public Foo get() {
            return new FooImpl("topic B");
        }
    });

またはJava 8:

    bind(Foo.class).annotatedWith(Names.named("firstFoo")).toProvider(() -> new FooImpl("first"));
    bind(Foo.class).annotatedWith(Names.named("secondFoo")).toProvider(() -> new FooImpl("second"));

そして、Fooインスタンスが必要なサービスのコンストラクターで:

@Inject
public MyService (
    @Named("firstFoo") Foo firstFoo,
    @Named("secondFoo") Foo secondFoo) {
}

私の場合、Foo:

public class FooImpl implements Foo {

    private String name;

    public FooImpl(String name) {
        this.name = name;
    }

    @Override
    public String getName() {
        return name;
    }
}

それが誰かを助けることを願っています。

7
NejcT

このクラスがファクトリーである場合、非静的getFooメソッドを持つGuice管理オブジェクトである必要があり、getFooメソッドは単に

new Foo(bar)

Guiceによってすべてのクラスをインスタンス化する必要はありません。

AssistedInject も参照してください。このファクトリーを自分で作成することを避け、Guiceに作成してもらいます。

1
JB Nizet