1

私は Dagger 2 で以下を設定しようとしています:
AnEventFinderには 2 つの部分があります: aTriggerFinderと an のArgFinderそれぞれには、多くの依存関係を持つ複雑なオブジェクトである多くの異なる実装があります。以下のコード サンプルは、別のオブジェクトに依存するEventFinderwith サンプルTriggerFinderとを正常にビルドします。ただし、モデル間でシングルトンとして共有したい非常に大きく、高価な定数オブジェクトです。の現在の実装では、 2 回ロードされます。メソッドをとしてマークしようとすると、次のエラーが発生します。ArgFinderWordNetWordNetWithWordNetEventFinderComponentWordNet@ProvidesWordNetModule@Singleton

Error: ArgFinderUsingWordNetComponent (unscoped) may not reference scoped bindings:
      @Singleton @Provides WordNet WordNetModule.provideWordNet()

しかし、注釈をコンポーネントのツリーの上に伝播@Singletonしても、他のエラーが発生するだけです。これを行う正しい方法はどうなりますか?

完全なコード:

import org.junit.Test;

import javax.inject.Inject;
import javax.inject.Named;

import dagger.Component;
import dagger.Module;
import dagger.Provides;

// WordNet - this is the expensive shared resource we would
// like to make a singleton
class WordNet {
  final String path;

  public WordNet(@Named("path") String path) {
    System.out.println("Loading Fake wordnet from " + path);
    this.path = path;
  }
}

@Module
class WordNetModule {
  final String path;

  public WordNetModule(String path) {
    this.path = path;
  }

  // uncommenting the line below causes errors
  //@Singleton
  @Provides
  public WordNet provideWordNet() {
    return new WordNet(path);
  }
}

interface TriggerFinder {

}

class TriggerFinderUsingWordnet implements TriggerFinder {
  WordNet wordNet;

  @Inject
  public TriggerFinderUsingWordnet(WordNet wordNet) {
    this.wordNet = wordNet;
  }
}

@Module(includes = WordNetModule.class)
class TriggerFinderWithWordnetModule {    
  @Provides
  public TriggerFinder provideTriggerFinder(TriggerFinderUsingWordnet triggerFinder) {
    return triggerFinder;
  }
}

interface ArgFinder {

}


class ArgFinderUsingWordnet implements ArgFinder {

  WordNet wordNet;

  @Inject
  public ArgFinderUsingWordnet(WordNet fakeWordNet) {
    this.wordNet = fakeWordNet;
  }
}
@Module(includes = WordNetModule.class)
class ArgFinderWithWordNetModule {

  @Provides
  public ArgFinder provideArgFinder(ArgFinderUsingWordnet argFinder) {
    return argFinder;
  }
}

// the composite object we wish to create
class EventFinder {

  private final TriggerFinder triggerFinder;
  private final ArgFinder argFinder;

  @Inject
  public EventFinder(TriggerFinder triggerFinder, ArgFinder argFinder) {
    this.triggerFinder = triggerFinder;
    this.argFinder = argFinder;
  }
}

// components to wire everything together
interface ArgFinderComponent {    
  ArgFinder argFinder();
}

interface TriggerFinderComponent {
  TriggerFinder triggerFinder();
}

@Component(modules = ArgFinderWithWordNetModule.class)
interface ArgFinderUsingWordNetComponent extends ArgFinderComponent {

}

@Component(modules = TriggerFinderWithWordnetModule.class)
interface TriggerFinderUsingWordNetComponent extends TriggerFinderComponent {

}

interface EventFinderComponent {
  EventFinder eventFinder();
}


@Component(dependencies = {ArgFinderUsingWordNetComponent.class,
    TriggerFinderUsingWordNetComponent.class})
interface WithWordNetEventFinderComponent extends EventFinderComponent {

}

public class DaggerComponentTest {
  @Test
  public void withWordNetTest() {
    final WordNetModule wordNetModule = new WordNetModule("myPath");

    DaggerWithWordNetEventFinderComponent.builder()
        .argFinderUsingWordNetComponent(
            DaggerArgFinderUsingWordNetComponent.builder().wordNetModule(wordNetModule).build())
        .triggerFinderUsingWordNetComponent(
            DaggerTriggerFinderUsingWordNetComponent.builder().wordNetModule(wordNetModule).build())
        .build().eventFinder();
  }
}
4

1 に答える 1

3

通常、最上位のコンポーネントをマークしてから、それを必要とする@Singletonすべてのサブコンポーネントをマークします。provide*()結局のところ、シングルトンはグローバル グラフ レベルでのみ保証されます。

下からマークを付け始めると@Singleton、一番上に到達するまで(経験したように)複数のエラーが発生します。おそらく、ロールバックして上から始める方が簡単でしょう@Component

于 2015-07-16T13:02:37.893 に答える