匕首2循环依赖

ben*_*nyl 18 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;
    ...
}
Run Code Online (Sandbox Code Playgroud)

这个想法是,在执行工作时,工作可以访问多个服务 - 其中一个是执行程序本身,这样工作就可以执行子工作.

可以看出,这里有一个循环依赖,但我发现很难打破.

主要问题是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();
}
Run Code Online (Sandbox Code Playgroud)

然后我将原始类修改为:

@Singleton
class WorkExecutor {
    @Inject DelayedProvider<ExecutionServices> services;
    ...
    public void execute(Work w){
        w.execute(services.get());
        ...
    }
    ...
}

class ExecutionServicesImpl implements ExecutionServices {
    @Inject WorkExecutor executor;
    ...
}
Run Code Online (Sandbox Code Playgroud)

然后为了创建我的应用程序,我必须做:

AppComponent acomp = DaggerAppComponent.create();
App = acomp.app();
acomp.configureLateBinding();
Run Code Online (Sandbox Code Playgroud)

但我不确定这是正确的行动方案 - 有更好的方法吗?

Joe*_*oeG 2

我不怀疑OP会喜欢这个,因为你想要一种方法让某些事情“错误”,工作“正确”。事实并非如此。每当遇到循环依赖项时,“正确”的解决方案是重构以删除该依赖项。

在您的情况下,WorkExecutor 是一个单例,因此它可能需要保持原样。然后应该修改 ExecutionServicesImpl 以删除对 WorkExecutor 的依赖。在不了解代码的具体情况的情况下,不能说太多。然而,让 ExecutionService 独立于它的“worker”可以减少耦合,从长远来看可能是一件非常好的事情。