我正在尝试在 Dagger 2 中设置以下内容:
AnEventFinder
有两个部分:aTriggerFinder
和 anArgFinder
每个部分都有许多不同的实现,它们本身就是具有许多依赖关系的复杂对象。下面的代码示例成功构建了一个EventFinder
with 示例TriggerFinder
,并且ArgFinder
它们都依赖于另一个对象WordNet
. 但是,WordNet
它是一个非常大、昂贵、恒定的对象,我想在模型之间作为单例共享。当前的实现WithWordNetEventFinderComponent
加载了WordNet
两次。如果我尝试将@Provides
方法标记WordNetModule
为 as @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();
}
}