我怎样才能提供' Dagger中的空洞方法

时间:2016-11-30 22:23:07

标签: java dependency-injection dagger-2

我尝试从Spring迁移项目,然后通过跟踪示例GitHub repo开始使用Dagger 2。

在Spring中,我可以在类级别使用注释来公开类的所有方法,包括void方法。我想在Dagger 2中这样做,即我想提供' void方法。

在下面的代码示例中,我可以将printRandomUUID方法移动到Printer接口。但是,我正在进行这项小练习,目标是迁移古典的Spring @Component@Service

什么是正确的方法?是否可以在组件或模块级别提供void方法?

public class Main {

 interface Printer {

    void printMsg(String msg);
 }

 static class ConsolePrinter implements Printer {

    @Override
    public void printMsg(String msg) {
        System.out.println(msg);
    }
 }

 @Singleton
 @Component(modules = ConsoleModule.class)
 interface HelloWorldApp {

    Printer getPrinter();

    //this doesn't compile -> java.lang.IllegalArgumentException: not a valid component method:
    void printRandomUUID();
 }

 @Module
 static class ConsoleModule {

    @Provides
    Printer providePrinter() {
        return new ConsolePrinter();
    }

    //this doesn't compile -> @Provides methods must return a value (not void)
    @Provides
    void printRandomUUID() {
        System.out.println(UUID.randomUUID().toString());
    }

 }

 public static void main(String[] args) {
    HelloWorldApp app = DaggerMain_HelloWorldApp.create();
    app.getPrinter().printMsg("Hello");
    System.out.println("-");
    //app.printRandomUUID();//here i want a void method to be consumed, from the component.
 }
}

1 个答案:

答案 0 :(得分:3)

这是不可能的(还)。与Spring不同,Dagger仅通过检查Component接口和Modules来配置。这意味着Dagger @Component方法必须match the format of the methods from the @Component documentation,并且目前无法提供委托给其他实例的任意代码或方法。

这并不是说组件不能有空方法:它们可以,但它们需要是一个单参数方法,注入@Inject - 带注释的方法和字段外部创建的实例。这些被称为members-injection methods,而不是void,它们也可以返回它们接受的类型以便于链接。

从不同的角度来看,我认为,出于简单和正确的原因,将任意业务逻辑与Dagger创建的组件相结合是一个坏主意:

  • 这样做可能违反了SRP或关注点分离:依赖注入的一个明显优势是将对象创建逻辑与其他业务逻辑分离。允许在对象创建组件上添加业务方法应该感觉与在业务组件中使用new一样不合适。 (是否应通过DI图提供每一个对象是另一天的争议话题。)
  • 如果你坚持最好的做法,避免副作用和其他重的提升"在构造函数/工厂/提供者中,您应该能够干净地推断出在Component方法中能够和不能发生什么。在组件上允许任意方法 - 特别是空方法 - 将与该实践相对立。
  • 如果您的应用程序使用单独的粒度库而不是单片编译步骤,那么从其自己的对象图中使用Component可能会在不引入依赖循环的情况下难以构建。当然,Dagger确实允许在自己的图形中注入一个组件,但是这样做可能会导致循环问题。
  • 使用现有结构可以很容易地表示类似的用例 - 通过图表可以像Louis Wasserman评论的那样使用Runnable,或者注入一个类似的单用途对象来保存方法 - 保持任意实现不受影响组件似乎不会导致功能或可读性的大量损失。在最坏的情况下,您需要一个额外的方法调用才能进入您定义的类。

如果我按原样进行迁移,我会在HelloWorldApp上创建一个名为HelloWorldMethods的类,并将我放在HelloWorldApp上的所有方法转移到该类上。如果这是Spring迁移中的常见模式,您甚至可以为它定义一个本地约定(例如,FooComponent附带FooMethods或FooUtil)。最后,如果你想隐藏Dagger实现细节(如在外部API中),你也可以编写自己的类来包装和使用你的Component,将重要的方法委托给内部Component并提供你需要的任意实现。