java - Dagger 2循环依赖

标签 java dagger-2

在我正在从事的一个项目中,我有两个高度相互依赖的类:

@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/

相关文章:

java - 如何在 apache Camel 中获取 DSL(领域特定语言)列表?

java - 如何制作 java 扫描仪的副本?

java - Dagger 构建错误

Android Dagger 2 - 如何使自定义作用域成为本地单例

java - 如何在 Java 中以原子方式将一个目录替换为另一个目录?

java - 在运行时从另一个类的哈希表中获取值

java - 在 JSP 提交按钮中使用 Servlet 变量

java - "provides"方法或注入(inject)类上的 Dagger 2 范围注释

android - 将 Dagger2 与 PreferenceFragmentCompat 结合使用

android - Dagger 2、库模块和@Singleton