在我正在从事的一个项目中,我有两个高度相互依赖的类:
@Singleton
class WorkExecutor {
@Inject Provider<ExecutionServices> services;
...
public void execute(Work w){
w.execute(services.get());
...
}
...
}
class ExecutionServicesImpl implements ExecutionServices {
@Inject WorkExecutor executor;
...
}
这个想法是,当执行一个工作时,该工作可以访问多个服务——其中之一是执行者本身,这样一个工作就能够执行子工作。
如您所见,这里存在循环依赖,但我发现很难打破。
主要问题是 WorkExecutor 在图形构建时实际上并不需要 ExecutionServices 对象的实例,而只需要稍后使用的提供者。遗憾的是,Dagger 不知道 WorkExecutor 不会从类的构造函数调用 ExecutionServices 提供程序,因此它猜测 ExecutionServices 依赖于 WorkExecutor,反之亦然。
我找到的一种可能的解决方案是按以下方式定义模块和组件:
interface DelayedProvider<T> extends Provider<T>{}
@Module
class AppModule {
Provider<ExecutionServices> delayedProvider = null;
@Provides DelayedProvider<ExecutionServices> provideDelayed() {
return () -> delayedProvider.get();
}
@Provides @Named("late-binding-conf") Void latebindingConf(Provider<ExecutionServices> eager){
this.delayedProvider = eager;
return null; //notice we returning Void and not void
}
}
@Component(modules=AppModule.class)
interface AppComponent {
App app();
@Named("late-binding-conf") Void configureLateBinding();
}
然后我将原始类修改为:
@Singleton
class WorkExecutor {
@Inject DelayedProvider<ExecutionServices> services;
...
public void execute(Work w){
w.execute(services.get());
...
}
...
}
class ExecutionServicesImpl implements ExecutionServices {
@Inject WorkExecutor executor;
...
}
然后为了创建我的应用程序,我必须这样做:
AppComponent acomp = DaggerAppComponent.create();
App = acomp.app();
acomp.configureLateBinding();
但我不确定这是正确的做法 - 是否有更好的方法?
最佳答案
我不怀疑 OP 会喜欢这个,因为你想要一种方法让事情变得“错误”,但工作“正确”。那不可能。每当遇到循环依赖时,“正确”的解决方案是重构以移除该依赖。
在您的情况下,WorkExecutor 是一个单例,因此它可能需要保持原样。然后应修改 ExecutionServicesImpl 以删除对 WorkExecutor 的依赖。在不知道代码细节的情况下,不能说太多。但是,让 ExecutionService 独立于它的“worker”可以减少耦合,从长远来看可能是一件非常好的事情。
关于java - Dagger 2循环依赖,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30121784/