已经发布了几个关于依赖注入的具体问题,例如何时使用它以及它有什么框架,
什么是依赖注入,何时/为什么应该或不应该使用它?
已经发布了几个关于依赖注入的具体问题,例如何时使用它以及它有什么框架,
什么是依赖注入,何时/为什么应该或不应该使用它?
当前回答
来自Christoffer Noring,Pablo Deeleman的书《学习角度-第二版》:
“随着我们的应用程序的增长和发展,我们的每一个代码实体都将在内部需要其他对象的实例,在软件工程领域中,这些对象被称为依赖关系。将这些依赖关系传递给依赖客户端的动作被称为注入,它还需要另一个代码主体(称为注入器)的参与。注入器将负责用于实例化和引导所需依赖项的功能,以便它们从成功注入客户端的那一刻起就可以使用。这一点非常重要,因为客户机不知道如何实例化自己的依赖关系,只知道为了使用它们而实现的接口。"
发件人:Anton Moiseev。《字体角度发展,第二版》一书:
“简而言之,DI帮助您以松散耦合的方式编写代码,并使代码更易于测试和重用。”
其他回答
什么是依赖注入?
依赖注入(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作为必需的依赖项。
“依赖注入”不就是指使用参数化构造函数和公共setter吗?
James Shore的文章展示了以下示例进行比较。
没有依赖注入的构造函数:公共类示例{私有数据库Thingie myDatabase;public Example(){myDatabase=新数据库Thingie();} public void doStuff(){... myDatabase.getData();... } } 具有依赖注入的构造函数:公共类示例{私有数据库Thingie myDatabase;公共示例(DatabaseThingie使用ThisDatabaseReplace){myDatabase=改用此数据库;}public void doStuff(){... myDatabase.getData();... } }
我将提出一个稍微不同的、简短而精确的依赖注入定义,侧重于主要目标,而不是技术手段(从这里开始):
依赖注入是创建静态、无状态的服务对象图,其中每个服务由其依赖关系。
我们在应用程序中创建的对象(无论我们是否使用Java、C#或其他面向对象语言)通常分为两类:无状态、静态和全局“服务对象”(模块),以及有状态、动态和本地“数据对象”。
模块图(服务对象图)通常在应用程序启动时创建。这可以使用容器(如Spring)完成,但也可以通过向对象构造函数传递参数来手动完成。这两种方法都有其优点和缺点,但在应用程序中使用DI肯定不需要框架。
一个要求是服务必须通过其依赖性进行参数化。这意味着什么完全取决于给定系统中采用的语言和方法。通常,这采用构造函数参数的形式,但使用setter也是一种选择。这也意味着(在调用服务方法时)对服务的用户隐藏服务的依赖关系。
何时使用?我会说,每当应用程序足够大时,将逻辑封装到单独的模块中,在模块之间使用依赖关系图,可以提高代码的可读性和可探索性。
在进行技术描述之前,首先用一个真实的例子来形象化它,因为你会发现很多技术知识需要学习依赖注入,但大多数人都无法理解它的核心概念。
在第一张图中,假设你有一家拥有很多单位的汽车工厂。汽车实际上是在装配单元中制造的,但它需要发动机、座椅和车轮。因此,装配单元依赖于这些所有单元,它们是工厂的依赖。
你可以感觉到,现在在这个工厂维护所有的任务太复杂了,因为除了主要任务(在组装单元组装汽车)外,你还必须关注其他单元。现在维护成本很高,而且厂房很大,因此需要额外的租金。
现在,看第二张图。如果你找到一些供应商公司,他们会以比你自己生产成本更低的价格为你提供车轮、座椅和发动机,那么现在你就不需要在工厂里生产了。您现在可以为您的装配单元租用一栋较小的建筑,这将减少您的维护任务,并降低额外的租赁成本。现在你也可以只专注于你的主要任务(汽车组装)。
现在我们可以说,组装汽车的所有依赖都是由供应商注入工厂的。这是一个真实的依赖注入(DI)示例。
现在用技术术语来说,依赖注入是一种技术,一个对象(或静态方法)提供另一个对象的依赖。因此,将创建对象的任务传递给其他人并直接使用依赖关系称为依赖注入。
这将帮助您现在通过技术说明学习DI。这将显示何时使用DI,何时不使用DI。
.
依赖注入意味着一种方式(实际上是任何方式),代码的一部分(例如类)可以以模块化的方式访问依赖项(代码的其他部分,例如它所依赖的其他类),而不必对它们进行硬编码(因此它们可以自由更改或重写,甚至可以根据需要在其他时间加载)
(顺便说一句,是的,对于一个相当简单的概念,它已经成为一个过度炒作的25美元的名字),我的25美分