Dependency injection 什么是;注射;构造函数注入和依赖项注入中的方法

Dependency injection 什么是;注射;构造函数注入和依赖项注入中的方法,dependency-injection,terminology,constructor-injection,Dependency Injection,Terminology,Constructor Injection,我读过关于依赖注入的文章。然后就来了 构造函数注入 吸气剂注入 塞特注射 界面注入 它们与依赖注入有何不同?或者它们都是相同的?注射在这里是什么意思?只是给类提供所需的对象/参数?类似于构造注入意味着将所需参数作为构造函数参数传递?还是我遗漏了什么? 依赖项注入是通过第三方提供依赖项来为类提供依赖项的行为 是最常见的依赖项注入形式构造函数注入是静态定义所需依赖项列表的行为,方法是将它们指定为类构造函数的参数 Setter注入(又称接口注入是方法注入的特化)是向消费类提供(或“注入”)依赖

我读过关于依赖注入的文章。然后就来了

  • 构造函数注入
  • 吸气剂注入
  • 塞特注射
  • 界面注入
它们与依赖注入有何不同?或者它们都是相同的?注射在这里是什么意思?只是给类提供所需的对象/参数?类似于构造注入意味着将所需参数作为构造函数参数传递?还是我遗漏了什么?

  • 依赖项注入是通过第三方提供依赖项来为类提供依赖项的行为

  • 是最常见的依赖项注入形式构造函数注入是静态定义所需依赖项列表的行为,方法是将它们指定为类构造函数的参数

  • Setter注入(又称接口注入是方法注入的特化)是向消费类提供(或“注入”)依赖性的替代形式

  • 据我所知,吸气剂注射并不存在。Getter只能检索值,不能设置值,这是依赖项注入的要求


因此构造函数注入Setter注入接口注入都是依赖注入的形式构造函数注入是DI最常见的形式,它强制创建具有所有必需依赖项的类构造函数注入因此应该是您首选的DI形式。然而,在某些情况下,方法注入属性注入也有意义。这本书(由Mark Seemann和我合著)详细介绍了这些形式的DI(特别是)。

然后在Dagger 2中有
@Inject
构造函数,这是不同的东西,可能被初级开发人员误认为是。看起来是这样的:

ListAdapter @Inject constructor() : RecyclerView.Adapter<ListViewHolder>() {
//code
}
class ListAdapter extends RecyclerView.Adapter<ListViewHolder>() {

@Inject
public ListAdapter(Context context) {

}

}
ListAdapter@injectconstructor():RecyclerView.Adapter(){
//代码
}
上面是Kotlin,在Java中是这样的:

ListAdapter @Inject constructor() : RecyclerView.Adapter<ListViewHolder>() {
//code
}
class ListAdapter extends RecyclerView.Adapter<ListViewHolder>() {

@Inject
public ListAdapter(Context context) {

}

}
类ListAdapter扩展了RecyclerView.Adapter(){ @注入 公共ListAdapter(上下文){ } } 这是Dagger 2的功能,允许您生成
@提供
,而无需实际写入模块中的
@提供
函数/空白


通过使用inject注释构造函数,您还告诉dagger有一个名为X的类,您需要一个上下文来实例化它。这与将其添加到模块中基本相同。

依赖项注入的三种形式是构造函数、setter、接口[和第四种上下文]。我从未听说过吸气剂注射,所以我不会提及它。注入就是一个对象或组件与另一个对象或组件(通常是一个类)的关系。如果没有依赖注入,组件被认为是“紧密耦合”的,如果它们有任何形式的关联。例如,考虑不使用依赖注入的类(java编写):

public class Salesman implements Worker {
     private Car itemForSale;
     public Salesman() {
          itemForSale = new Car("BMW");
     }
     public void printItemSold() {
          System.out.println("The salesman sold a " + itemForSale.name() 
          + " at price $"+itemForSale.price());
     }
}
public class Salesman implements Worker {
     private Item itemForSale;
     public Salesman(Item item){
          itemForSale = item;
     }
     public void printItemSold(){
          System.out.println("salesman sold a " + itemForSale");
     }
}
在这里,saller类与Car类紧密耦合。考虑到销售人员实际上也可以销售零件、工具和服务。但是,itemForSale字段是一个汽车对象,这里的默认构造函数是将itemForSale设置为汽车对象。如果我们将构造函数更改为公共销售人员(字符串carName,double carPrice),我们的耦合会稍微松一些,但这仍然不会使销售人员和汽车解耦——Saleman对象的功能仍然“依赖”汽车对象

下面是构造函数依赖项注入的一个示例:

public class Salesman implements Worker {
     private Car itemForSale;
     public Salesman() {
          itemForSale = new Car("BMW");
     }
     public void printItemSold() {
          System.out.println("The salesman sold a " + itemForSale.name() 
          + " at price $"+itemForSale.price());
     }
}
public class Salesman implements Worker {
     private Item itemForSale;
     public Salesman(Item item){
          itemForSale = item;
     }
     public void printItemSold(){
          System.out.println("salesman sold a " + itemForSale");
     }
}
现在我们可以在另一个类中编写:

Item car = new Car("Jeep", 8900); // the Car class implements the Item item class/interface
Salesman salesman = new Salesman(car);
salesman.printItemSold();

Item part = new Part("tires", 67.99); // the Part class also implements the Item class/interface
Salesman salesman = new Salesman(part);
salesman.printItemSold();

... and so on.
在这种简单的情况下可能很难看到的关键好处是saller对象不依赖于Car类。为了涵盖所有不同类型的销售对象,我们不需要汽车领域、零件领域、服务领域等,也不需要实现逻辑,例如

if (car != null) 
     printItemSold(car) 
else if (part != null)
     printItemSold(part)
...
相反,我们所需要做的只是提供(或注入)销售人员向销售人员对象销售的物品

Setter注入的工作方式大致相同,只是它使用Setter而不是构造函数。如果我们想改变出售的物品,而不必每次都制作一个新的物品,这可能是有益的

public class Salesman implements Worker {
     private Item itemForSale;
     public Salesman() { }
     public void setItem(Item item){
          this.itemForSale = item;
     }
     ...
} 
现在我们可以做:

Salesman salesman = new Salesman();
salesman.setItem(new Car("Toyota", 23938.23);
salesman.print();
salesman.setItem(new Service("oil change", 17.78);
salesman.print();
我认为可以肯定地说,构造函数注入通常与setter注入一起实现,因为一旦实现了前一种形式,就很容易实现后一种形式

我不会进入接口注入,因为我以前没有使用过它,可能会给你错误的信息。若您碰巧正在使用JavaSpring,请知道Spring只使用构造函数和setter注入,而不使用接口

最后,上下文依赖注入并不是大多数人在使用术语依赖注入时所想的。但对我来说,当我试图了解依赖注入是什么时,我最关心的是它(很抱歉,如果下面的解释没有那么有用的话——我很难用Java Spring以外的任何其他术语来解释)。假设您有一个复杂的对象,比如数据库连接,它有许多字段和一个应该仔细管理的生命周期

您可以将其设置为类中的字段,对其进行配置,建立或打开它,开始和结束事务,并确保在程序终止时关闭它,所有这些都是您自己完成的。然而,如果您所要做的只是声明您想要一个连接对象,然后为您管理该连接,那就太好了。连接仅在需要时打开,在