2016-10-19 8 views
1

補助注入を実行中にエラーが発生しました。Guice assisted、binding order

助けられた注射は私が助けられたPersonクラスに頼るマネージャと呼ばれる別のクラスを導入するまで働いた。マネージャーはPerson (@Assited Address)を使用します。コードはインジェクタグラフを作成する時点でブレークします。それ以上は行きません。オブジェクトAはまた、暗黙のうちに

PlsのノートA.を通じて支援実際には(Aに依存して)、その後Bを支援しているとき

Injector injector = Guice.createInjector(myModule); 

は直感的に、私は理解し、私はSOにチェック。私はColinDのような人は間違いなく好奇心のうち How to use Guice's AssistedInject? How to bind Assisted Injected class to interface?

答えを知っているだろうと思う、Guiceの設定ミスを発見し、学習曲線を容易にするが良い技術/ツールですか? ProvisionListenerをオンにし、グラフライブラリを使用しました。それは少し助けます。

public class Person implements PersonInterface { 
private String name; 
private Address address; 

@Inject 
public Person(String name, @Assisted Address address) { 
     this.name = name; 
     this.address = address; 
} 

} 

public interface PersonInterface { 
    public String getName(); 
    public Address getAddress(); 
} 

public interface PersonFactory { 
    public PersonInterface create(Address address); 
} 

public class Address { 
private final String address; 

public Address(String address) { 
    super(); 
    this.address = address; 
} 
} 

public class Manager implements IManager { 
private final Person person; 
@Inject 
public Manager(Person person) { 
    this.person=person; 
} 
... 
} 

configure() { 

    install(new FactoryModuleBuilder() 
      .implement(PersonInterface.class, Person.class) 
      .build(PersonFactory.class)); 

    // 
    bind(IManager.class).to(Manager.class); 
} 

あなたのモジュールに結合これを入れると、実際のエラーが

com.google.inject.CreationException: Unable to create injector, see the following errors: 

1) No implementation for ...assisted_inject.Address annotated with @com.google.inject.assistedinject.Assisted(value=) was bound. 
    while locating ....assisted_inject.Address annotated with @com.google.inject.assistedinject.Assisted(value=) 
    for parameter 2 at ....assisted_inject.Person.<init>(Person.java:13) 

答えて

2

です:

bind(IManager.class).to(Manager.class); 

のGuiceはManagerクラスの新しいインスタンスを作成しようとします。これは、@Injectでアノテーションされたコンストラクタ(または1つだけ)を検索します。または、aは、プライベートではないフォールバックの引数のないコンストラクタです。これは、Guiceのが使用するコンストラクタです。

@Inject 
public Manager(Person person) { 
    this.person=person; 
} 

今同じ規則次のGuiceは適切なコンストラクタを使用してPersonをインスタンス化しようとすると、それはここにはまります:

@Inject 
public Person(String name, @Assisted Address address) { 
    this.name = name; 
    this.address = address; 
} 

それは与えます@Assistedアノテーションのためにアドレスをインスタンス化しようとすると、この注釈はBindingAnnotationであり、Guiceはこれらを特別に扱います。明示的なバインディングを見つけようとしますが、それはありません。バインディングアノテーションについて読むと、その理由を理解できます。

上司がステートフルであると明らかにあなたがこれらのマネージャーのファクトリを作成することも、単一の人、例えばを管理しているので:

public interface IManagerFactory { 
    public IManager getIManager(PersonInterface p); 
} 

次にあなたがIManager、例えば必要があります:

public interface IManager { 
    public String getPersonName(); 
} 

補助注入を使用するインプリメンテーション:

public class Manager implements IManager { 
    private final PersonInterface person; 

    @Inject 
    public Manager(@Assisted PersonInterface person) { 
     this.person = person; 
    } 

    @Override 
    public String getPersonName() { 
     return person.getName(); 
    } 

} 

あなたのモジュールでこれらをバインドすることができます。

class MyModule extends AbstractModule { 
    protected void configure() { 
     install(new FactoryModuleBuilder() 
      .implement(PersonInterface.class, Person.class) 
       .build(PersonFactory.class)); 


     install(new FactoryModuleBuilder() 
      .implement(IManager.class, Manager.class) 
      .build(IManagerFactory.class)); 
     } 
    } 

は工場を注入:

@Inject 
PersonFactory pf; 

@Inject 
IManagerFactory manF; 

し、それに応じてそれらを使用し、例えば:

public void testGuice() { 
    PersonInterface pi = pf.create(new Address("boh")); 
    IManager im = manF.getIManager(pi); 

    System.out.println(im.getPersonName()); 
} 
+0

ルチョ、ありがとう。あなたの説明は全部意味がありました。サイドのコメント、私はBindingAnnotationが何か他のもののために設計されていると思っていました。 GuiceがAssisted pathを違った方法で構築していると思われ、より賢明なエラーメッセージが表示され、 が設定に瑕疵があることを示しています(工場不足) – Vortex

+1

@Vortex '@ Assisted'が' @BindingAnotation'それがどのように実装されているかによって、生成されるファクトリメソッドは子インジェクタを作成し、パラメータ値に '@Assisted Address'のバインディングを追加し、' Person'を注入します。 –