当前位置: 首页 > 知识库问答 >
问题:

Guice辅助注入过度使用替代,依赖注入vs非DI构造函数

公冶森
2023-03-14

我喜欢在构造函数中传递运行时依赖项的主要原因是:

  1. 它使依赖关系成为必需的
  2. 它提供了设置实例变量的中心位置
  3. 将依赖项设置为实例变量,可以避免在类中从一个方法传递到另一个方法,或者将它分两次或多次传递给两个或更多个公共方法

这导致我在使用Guice时使用了很多辅助注射。与不使用DI相比,这会产生额外的代码,因此阅读以下内容:辅助注入到底有多有用?

似乎大多数人不会使用辅助注入在构造函数中传递运行时(派生的,在启动时不可用)依赖项,而是在单个方法中传递它们。这对于上面stackoverflow帖子中给出的简单类来说很好,其中只有一个依赖于依赖项的方法:

public class SomeClass {
    @Inject
    SomeClass(...) {
        ...
    }

    public void doWork(int s) { /* use s */ ... }
}

但是,如果类有许多使用依赖项的方法呢?您是否将其从公共方法传递到私有方法,并要求它传递到所有公共方法?例如:

public class SomeClass {
    @Inject
    SomeClass(...) {
        ...
    }

    public void doWork(int s) { 
     /*some code */
     someOtherMethod(s);
     anotherMethod(s);  

    }
    //any private method that needs it gets it passed in as a param
    private void someOtherMethod(int s)...
    private void anotherMethod(int s)...

    //require it passed in all public methods that need it
    public void anotherPublic(int s){
      someOtherMethod(s);
    }
}

与使用构造函数相反,这增加了一点额外的代码,如下所示:

public class SomeClass {
    private int s;
    SomeClass(int s) {
        this.s = s;
    }

    public void doWork() { 
     someOtherMethod();
     anotherMethod();  

    }
    private void someOtherMethod()...
    private void anotherMethod()...

    public void anotherPublic(){}
}

还是像这样从服务方法设置实例var?

public class SomeClass {
    Integer s;
    @Inject
    SomeClass(...) {
        ...
    }

    public void doWork(Integer s) { 
     /***set instance var this time***/
      this.s = s;
     someOtherMethod();
     anotherMethod();  

    }
    private void someOtherMethod()...
    private void anotherMethod()...

    public void anotherPublicMethod(){
     if(s==null){ //check if s was set already
         throw new IllegalStateException();
      }else{
      /* do something else */
      }
    }


}

还是将依赖项作为参数传递到另一个公共方法中,并在那里设置实例变量?例如:

public class SomeClass {
    @Inject
    SomeClass(...) {
        ...
    }

    public void doWork(Integer s) { 
     /***set instance var this time***/
      this.s = s;
     someOtherMethod();
     anotherMethod();  

    }
    private void someOtherMethod()...
    private void anotherMethod()...

    public void anotherPublicMethod(Integer s){
       this.s = s;
      /* do something else */
    }


}

所以我认为,与使用普通的构造函数相比,将参数从一个方法传递到另一个方法或者抛出非法的状态异常来检查它并不理想,但是显然任何框架/模式都有优点/缺点。

如果我没有以理想的方式分离我的对象,请让我知道你使用的一些准则,即“我只使用每个服务类的一个公共方法,见这本书或关于它的帖子:。”.

在上述情况下,你们会怎么做?

共有1个答案

冯良才
2023-03-14

您在问题中明确了使用辅助注入的一些重要原因:它确保了对象实例只存在于完全初始化的状态中,保持了依赖关系,并使对象的公共接口不需要在每个方法中使用可预测的参数。

除了你提到的那些之外,我真的没有任何选择可以添加:

  • 为该依赖项添加setter方法,可能需要IllegalStateException检查或良好的默认值
  • 使用相同的IllegalStateException检查创建initialize(ints)伪构造函数方法
  • 在个别方法中采用参数
  • 自定义工厂替换FactoryModuleBuilder样板,从而创建更多您试图避免的额外样板

我最喜欢的是你似乎在两者之间做出决定——辅助注入或在每种方法中获取参数——主要是因为它们都使对象始终处于可预测的、可用的状态。我在它们之间的决定取决于对象应该携带什么样的状态,该状态是否可变,以及我想如何控制实例。对于Car.licensePlateDigital,车牌号可能会随着汽车实例而变化;每辆车都有一个车牌号,(在本例中)永远不会变化,没有它汽车就无效,所以它应该是一个构造函数参数。相反,存储库

请记住,辅助注入不应该真的需要那么多额外的代码:

/** In module: install(new FactoryModuleBuilder().build(SomeClass.Factory.class)); */
public class SomeClass {
  public interface Factory {
    SomeClass create(int s);
  }

  private final int s;

  @Inject
  SomeClass(/* ..., */ @Assisted int s) {
    this.s = s;
  }

  public void doWork() { /* ... */ }
}

 类似资料:
  • 我正在使用Guice Assisted Inject库为我建立一个工厂。我目前的设置如下: 这迫使我使用< code > factory . create controller(first,factory . create second(first))显式创建一个< code>SecondDep。是否可以更改我的绑定,这样我就可以简单地执行< code > factory . create con

  • 我想引导一系列处理元素,并通过Guice将它们连接在一起。让我们假设以下路径: 需要一些输入 由实现需要 由实现需要 由实现需要 的依赖关系只能在运行时解决,而不能在配置时解决。通常的方法是在这种情况下使用辅助注入来创建工厂,该工厂将缺少的实例作为参数,如下所示: 但我真正想要的是这样的: 我不想在整个层次结构中手动传递AImpl的特定依赖项。使用Guice可以实现这一点吗?如果没有,在保持注射的

  • 我需要重构现有的抽象类来实现依赖注入,但是这个类有两个接受其他参数的构造函数。 我需要注入一些接口,并避免在构造函数中传递任何其他参数,如“settingsId”和“Setting”。所以我的想法是在创建此类的实例后创建两种方法来设置这些参数。 但它看起来不是一个合适的解决方案,因为如果开发人员忘记在创建实例后运行这些方法之一,我们将来可能会得到一个异常(对象未设置为引用...)。我应该如何正确执

  • 我正试图在计算机上实现这个例子https://developer.android.com/jetpack/docs/guide.这就解释了Android应用程序的结构。 当我使用相同的代码时,我会出现以下错误。 我可以找出这个错误与 当我为ViewModel编写默认的零输入构造函数时,我得到了以下错误。 我想不出这个错误的原因和解决方法。

  • 我有一个关于 azure 函数 v1 中的依赖注入的新问题。 实际情况: 我有一个azure函数V1,我想在其中引用我的业务服务,而无需重新发明轮子即可使用我的服务。我在Internet上搜索并找到了这篇来自Microsoft的有趣文章。 但是,它似乎只适用于azure函数v2(. net core),因为每当我尝试安装时,我总是收到以下错误: 检测到Microsoft.Azure.WebJobs

  • 我有一个工厂是这样的: 这样的类: 如何正确使用Google Guice来做同样的事情?我尝试了辅助注射,但我不确定如何创建“UrlBuilder”。谁能帮忙?