已经发布了几个关于依赖注入的具体问题,例如何时使用它以及它有什么框架,
什么是依赖注入,何时/为什么应该或不应该使用它?
已经发布了几个关于依赖注入的具体问题,例如何时使用它以及它有什么框架,
什么是依赖注入,何时/为什么应该或不应该使用它?
当前回答
什么是依赖注入?
依赖注入(DI)意味着分离彼此依赖的对象。假设对象A依赖于对象B,因此想法是将这些对象彼此分离。我们不需要使用new关键字对对象进行硬编码,而是在运行时共享对对象的依赖关系,而不管编译时间如何。如果我们谈论
依赖注入在Spring中的工作原理:
我们不需要使用new关键字硬编码对象,而是在配置文件中定义bean依赖关系。弹簧容器将负责连接所有部件。
控制反转(IOC)
IOC是一个通用概念,可以用多种不同的方式表达,依赖注入是IOC的一个具体例子。
两种类型的依赖注入:
构造器注入沉淀剂注入
1.基于构造函数的依赖注入:
当容器调用具有多个参数的类构造函数时,就完成了基于构造函数的DI,每个参数表示对其他类的依赖。
public class Triangle {
private String type;
public String getType(){
return type;
}
public Triangle(String type){ //constructor injection
this.type=type;
}
}
<bean id=triangle" class ="com.test.dependencyInjection.Triangle">
<constructor-arg value="20"/>
</bean>
2.基于Setter的依赖注入:
基于Setter的DI是在调用无参数构造函数或无参数静态工厂方法来实例化bean之后,通过容器调用bean上的Setter方法来实现的。
public class Triangle{
private String type;
public String getType(){
return type;
}
public void setType(String type){ //setter injection
this.type = type;
}
}
<!-- setter injection -->
<bean id="triangle" class="com.test.dependencyInjection.Triangle">
<property name="type" value="equivialteral"/>
注:对于强制依赖项使用构造函数参数,对于可选依赖项使用setter,这是一个很好的经验法则。注意,如果我们在setter上使用基于@Required的注释,则可以将setter作为必需的依赖项。
其他回答
我在松耦合方面发现了一个有趣的例子:
来源:了解依赖注入
任何应用程序都由许多对象组成,这些对象相互协作以执行一些有用的任务。传统上,每个对象都负责获取自己对与其协作的依赖对象(依赖关系)的引用。这导致了高度耦合的类和难以测试的代码。
例如,考虑Car对象。
汽车依靠轮子、发动机、燃料、电池等运转。传统上,我们定义此类依赖对象的品牌以及Car对象的定义。
无依赖注入(DI):
class Car{
private Wheel wh = new NepaliRubberWheel();
private Battery bt = new ExcideBattery();
//The rest
}
在这里,Car对象负责创建从属对象。
如果我们希望在初始NepaliRubberWheel()穿孔后更改其从属对象的类型(例如Wheel),该怎么办?我们需要重新创建Car对象及其新的依赖项,例如ChineseRubberWheel(),但只有Car制造商才能做到这一点。
那么依赖注入为我们做了什么。。。?
当使用依赖注入时,对象在运行时而不是编译时(汽车制造时)被赋予依赖性。因此,我们现在可以随时更改轮子。在这里,相关性(轮子)可以在运行时注入Car。
使用依赖注入后:
这里,我们在运行时注入依赖项(Wheel和Battery)。因此有了这个词:依赖注入。我们通常依赖于Spring、Guice、Weld等DI框架来创建依赖关系并在需要时注入。
class Car{
private Wheel wh; // Inject an Instance of Wheel (dependency of car) at runtime
private Battery bt; // Inject an Instance of Battery (dependency of car) at runtime
Car(Wheel wh,Battery bt) {
this.wh = wh;
this.bt = bt;
}
//Or we can have setters
void setWheel(Wheel wh) {
this.wh = wh;
}
}
其优点是:
分离对象的创建(换句话说,将使用与对象的创建分开)能够替换依赖项(例如:车轮、电池),而不改变使用它的类(汽车)促进“代码到接口而不是实现”原则在测试期间创建和使用模拟依赖关系的能力(如果我们想在测试期间使用模拟轮而不是真实实例,我们可以创建模拟轮对象并让DI框架注入Car)
针对5岁儿童的依赖注入。
当你自己去把冰箱里的东西拿出来时,你可能会引起问题。你可能会让门开着,你可能会得到妈妈或爸爸不希望你拥有的东西。你甚至可能在寻找我们甚至没有或已经过期的东西。
你应该做的是陈述一个需要,“我需要午餐时喝点东西”,然后我们会确保你坐下吃饭时有东西。
这意味着对象应该只具有完成其工作所需的依赖项,并且依赖项应该很少。此外,如果可能的话,对象的依赖关系应该是接口,而不是“具体”对象。(具体对象是用关键字new创建的任何对象。)松散耦合促进了更高的可重用性,更容易维护,并允许您轻松地提供“模拟”对象来代替昂贵的服务。
“依赖注入”(DI)也称为“控制反转”(IoC),可以用作鼓励这种松散耦合的技术。
实施DI有两种主要方法:
构造函数注入设值注入
构造函数注入
这是一种将对象依赖关系传递给构造函数的技术。
注意,构造函数接受接口而不是具体对象。此外,请注意,如果orderDao参数为空,则会引发异常。这强调了接受有效依赖的重要性。在我看来,构造函数注入是赋予对象依赖关系的首选机制。在调用对象时,开发人员很清楚需要向“Person”对象提供哪些依赖关系才能正确执行。
沉淀剂注入
但是考虑下面的例子……假设您有一个类,它有十个没有依赖关系的方法,但是您要添加一个新方法,它确实依赖于IDAO。您可以将构造函数更改为使用构造函数注入,但这可能会迫使您更改所有的构造函数调用。或者,您可以添加一个新的构造函数来获取依赖项,但是开发人员如何轻松地知道何时使用一个构造函数而不是另一个构造函数。最后,如果依赖项的创建成本很高,为什么要创建它并传递给构造函数,因为它可能很少使用?“Setter Injection”是另一种DI技术,可用于此类情况。
Setter注入不会强制将依赖项传递给构造函数。相反,依赖项被设置到需要的对象公开的公共财产上。正如前面所暗示的,这样做的主要动机包括:
支持依赖注入而无需修改遗留类的构造函数。允许在需要时尽可能晚地创建昂贵的资源或服务。
下面是上述代码的示例:
public class Person {
public Person() {}
public IDAO Address {
set { addressdao = value; }
get {
if (addressdao == null)
throw new MemberAccessException("addressdao" +
" has not been initialized");
return addressdao;
}
}
public Address GetAddress() {
// ... code that uses the addressdao object
// to fetch address details from the datasource ...
}
// Should not be called directly;
// use the public property instead
private IDAO addressdao;
依赖注入是基于框架构建的“控制反转”原则的一种实现。
GoF的“设计模式”中所述的框架是实现主控制流逻辑的类,从而使开发人员能够这样做,这样框架实现了控制原则的反转。
作为一种技术而不是作为类层次结构实现的方法,IoC原则只是依赖注入。
DI主要包括将类实例的映射和对这些实例的类型引用委托给外部“实体”:对象、静态类、组件、框架等。。。
类实例是“依赖项”,调用组件通过引用与类实例的外部绑定是“注入”。
显然,从OOP的角度来看,您可以以多种方式实现该技术,例如,构造函数注入、setter注入、接口注入。
授权第三方执行将引用与对象匹配的任务,这在您希望将需要某些服务的组件与同一服务实现完全分离时非常有用。
这样,在设计组件时,您可以只关注其体系结构和特定逻辑,信任与其他对象协作的接口,而不必担心所使用的对象/服务的任何类型的实现更改,如果您正在使用的同一对象将被完全替换(显然是尊重接口)。
让我们想象一下,你想去钓鱼:
没有依赖注入,你需要自己处理所有的事情。你需要找一艘船,买一根鱼竿,寻找诱饵等等。当然,这是可能的,但这给你带来了很多责任。在软件方面,这意味着你必须对所有这些东西进行查找。通过依赖注入,其他人负责所有准备工作,并为您提供所需的设备。你将收到(“被注射”)船、鱼竿和鱼饵——所有这些都准备好使用。