Spring 框架的依赖注入和控制反转是什么?

“依赖注入”和“控制反转”经常被认为是使用 Spring 框架开发 Web 框架的主要优势

如果可能的话,谁能用一个简单的例子来解释一下这是什么?

184544 次浏览
  • 由于 依赖注入的存在,Spring 有助于创建松散耦合的应用程序。
  • 在 Spring 中,对象定义它们的关联(依赖关系) ,并且不用担心它们将如何获得这些 依赖关系。Spring 负责提供创建对象所需的依赖项。

例如 : 假设我们有一个对象 Employee,它依赖于对象 Address。我们将定义一个对应于 Employee的 bean,它将定义对对象 Address的依赖关系。

当 Spring 尝试创建一个 Employee对象时,它将看到 EmployeeAddress有依赖关系,因此它将首先创建 Address对象(依赖对象) ,然后将其注入到 Employee对象中。

  • 控制反转(物流中心)和依赖注入(督察)可互换使用。IoC 是通过 DI 实现的。DI 是提供依赖关系的过程,IoC 是 DI 的最终结果。(注:DI 不是实现 IoC 的唯一方法。还有 其他方式。)

  • 通过 DI,创建对象的责任从我们的应用程序代码转移到 Spring 容器; 这种现象称为 IoC。

  • 依赖注入可以通过 setter 注入或构造函数注入来完成。

我将写下我对这两个术语的简单理解: (为了快速理解,请阅读示例)

  • 依赖注入:
    依赖注入一般指 ABc0。
    在实践中,这意味着该方法不直接依赖于特定的实现; 满足需求的任何实现都可以作为参数传递。< br > < br > 通过这个对象的实现定义了它们的依赖关系,Spring 使它可用。 < br > 这导致了松散耦合的应用程序开发。

    快速示例: EMPLOYEE 对象在创建时,它将自动创建地址对象(如果地址被 EMPLOYEE 对象定义为依赖项) * . < br >

  • 控制反转容器:
    这是 IoC 管理 java 对象 < br > 框架的共同特征——通过它的 BeanFactory 从实例化到销毁。< br >-IoC 容器实例化的 Java 组件称为 bean,以及为其配置和编码的 IoC 容器管理 bean 的范围、生命周期事件和任何 AOP 特性。< br > < br > QUICK EXAMPLE:Inversion of Control is about getting freedom, more flexibility, and less dependency. When you are using a desktop computer, you are slaved (or say, controlled). You have to sit before a screen and look at it. Using keyboard to type and using mouse to navigate. And a bad written software can slave you even more. If you replaced your desktop with a laptop, then you somewhat inverted control. You can easily take it and move around. So now you can control where you are with your computer, instead of computer controlling it.通过实现控制反转,软件/对象消费者获得了对软件/对象更多的控制/选项,而不是被控制或拥有更少的选项。< br > < br > 控制反转作为设计指引的目的如下: < br >-某个任务的执行与实现是分离的。< br >-每个模块都可以专注于它的设计目的。< br >-模块不对其他系统做什么进行假设,而是依赖于它们的契约。替换模块对其他模块没有副作用

我将在这里保持抽象的东西,你可以访问下面的链接详细了解的主题。

很好的例子

详细解释

Spring: Spring 是 Java 平台的“控制反转”容器。

控制反转(IoC) : 控制反转(IoC)是一种面向对象的编程实践,其中对象耦合在运行时被一个“汇编器”对象所限制,并且通常在编译时使用静态分析是不可知的。

依赖注入(DI) : “依赖注入是一种软件设计模式,它允许去除硬编码的依赖关系,并允许在运行时或编译时更改这些依赖关系。”维基百科。

在 Employee 中获取地址实例的传统方法是创建 Address 类的新实例。Spring 创建了所有依赖于我们的对象,因此我们不需要担心对象。

所以在 Spring 中,我们只依赖于为我们提供依赖对象的 Spring 容器。

在 Spring 对象中是松散耦合的,也就是说,每个类彼此独立,因此所有东西都可以单独测试。但是当使用这些类时,一个类可能依赖于需要首先实例化的其他类。

因此,我们告诉 spring 类 A 依赖于类 B,因此,当为类 A 创建 bean (类似类)时,它在类 A 之前实例化类 B,并使用 setter 或构造函数 DI 方法在类 A 中注入类 B。也就是说,我们在运行时告诉 Spring 依赖关系。我是督察。

因为,我们把创建对象(bean)、维护对象及其聚合的责任分配给 Spring,而不是硬编码,我们称之为控制反转(IOC)。

控制反转(IOC) :

IoC 是一种设计模式,它描述反转系统中的控制流,因此执行流不受中心代码段的控制。这意味着组件应该只依赖于其他组件的抽象,而不负责处理依赖对象的创建。相反,对象实例在运行时由 IoC 容器通过依赖注入(DI)提供。

IoC 支持更好的软件设计,有利于软件组件的重用、松散耦合和轻松测试。

依赖注入:

DI 是一种将依赖项传递到对象构造函数的技术。如果对象已经从容器中加载,那么容器将自动提供其依赖项。这允许您使用依赖项,而不必手动创建实例。这减少了耦合,并使您能够更好地控制对象实例的生命周期。

点击查看更多

控制反转 它意味着将创建和实例化 Spring bean 的控制权交给 Spring IOC 容器,开发人员所做的唯一工作就是在 Spring xml 文件中配置 bean。

依赖注入

考虑一个类 Employee

class Employee {
private int id;
private String name;
private Address address;


Employee() {
id = 10;
name="name";
address = new Address();
}




}

考虑班级地址

class Address {
private String street;
private String city;


Address() {
street="test";
city="test1";


}
}

在上面的代码中,只有在 Employee 类被实例化时才会设置地址类值,这是 Address 类对 Employee 类的依赖关系。Spring 使用依赖注入概念解决了这个问题,提供了两种注入依赖关系的方法。

  1. 塞特注射

Employee 类中的 Setter 方法,该方法接受 Address 类的引用

public void setAddress(Address addr) {
this.address = addr;
}
  1. 构造函数注入

接受 Address 的 Employee 类中的构造函数

Employee(Address addr) {
this.address = addr;
}

通过这种方式,Address 类值可以使用 setter/构造函数注入来独立设置。

控制反转是软件架构的通用设计原则,有助于创建易于维护的可重用的模块化软件框架。

它是一种设计原则,其中控制流是从泛型编写的库或可重用代码“接收”的。

为了更好地理解它,让我们看看我们在早期编码时是如何编码的。在过程/传统语言中,业务逻辑通常控制应用程序的流程,并“调用”通用或可重用的代码/函数。例如,在一个简单的控制台应用中,我的控制流程是由程序的指令控制的,这些指令可能包括对一些通用可重用函数的调用。

print ("Please enter your name:");
scan (&name);
print ("Please enter your DOB:");
scan (&dob);


//More print and scan statements
<Do Something Interesting>


//Call a Library function to find the age (common code)
print Age

相反,对于 IoC,框架是“调用”业务逻辑的可重用代码。

例如,在一个基于窗口的系统中,一个框架已经可以创建 UI 元素,如按钮、菜单、窗口和对话框。当我编写应用程序的业务逻辑时,将是框架的事件调用我的业务逻辑代码(当一个事件被激发时) ,而不是相反。

尽管框架的代码不知道我的业务逻辑,但它仍然知道如何调用我的代码。这是通过使用事件/委托、回调等实现的。这里的流量控制是“倒置”的。

因此,控制流不依赖于静态绑定的对象,而是依赖于整个对象图和不同对象之间的关系。

依赖注入是一种设计模式,它实现 IoC 原则来解决对象的依赖性。

简单地说,当您尝试编写代码时,您将创建和使用不同的类。一个类别(A 类别)可以使用其他类别(B 类别及/或 D 类别)。所以 B 类和 D 类是 A 类的依赖关系。

一个简单的比喻就是一个类别汽车。一辆汽车可能依赖于其他类别,如引擎,轮胎和更多。

依赖注入建议不要使用依赖类(Class Car 在这里)来创建依赖项(Class Engine 和 Class Tyre) ,而应该使用依赖项的具体实例来注入 Class。

让我们用一个更实际的例子来理解。请考虑您正在编写自己的 TextEditor。在其他方面,您可以拥有一个拼写检查器,它为用户提供了检查文本中的拼写错误的工具。此类代码的简单实现可以是:

Class TextEditor
{


//Lot of rocket science to create the Editor goes here


EnglishSpellChecker objSpellCheck;
String text;


public void TextEditor()


{


objSpellCheck = new EnglishSpellChecker();


}


public ArrayList <typos> CheckSpellings()
{


//return Typos;


}


}

乍一看,一切都很美好。用户将写一些文本。开发人员将捕获文本并调用 CheckSpellings 函数,并找到一个他将显示给用户的拼写错误列表。

一切似乎都很好,直到有一天一个用户开始在编辑器中写法语。

为了支持更多的语言,我们需要更多的拼写检查器,可能是法语,德语,西班牙语等。

在这里,我们创建了一个紧密耦合的代码,“ English”SpellChecker 与我们的 TextEditor 类紧密耦合,这意味着我们的 TextEditor 类依赖于 EnglishSpellChecker,或者换句话说 EnglishSpellCheker 是 TextEditor 的依赖项。我们需要删除这个依赖项。此外,我们的文本编辑器需要一种方法来保持具体的参考任何拼写检查基于开发人员的自由裁量权在运行时。

因此,正如我们在 DI 的介绍中看到的,它建议类应该注入它的依赖项。因此,将所有依赖项注入到被调用的类/代码中应该是调用代码的责任。因此,我们可以将代码重新构造为

interface ISpellChecker
{


Arraylist<typos> CheckSpelling(string Text);


}


Class EnglishSpellChecker : ISpellChecker


{


public override Arraylist<typos> CheckSpelling(string Text)


{


//All Magic goes here.


}


}






Class FrenchSpellChecker : ISpellChecker


{


public override Arraylist<typos> CheckSpelling(string Text)


{


//All Magic goes here.


}


}

在我们的示例中,TextEditor 类应该接收 ISpellChecker 类型的具体实例。

现在,可以在构造函数、公共属性或方法中注入依赖项。

让我们尝试使用构造函数 DI 修改我们的类。修改后的 TextEditor 类如下所示:

Class TextEditor


{


ISpellChecker objSpellChecker;


string Text;






public void TextEditor(ISpellChecker objSC)


{


objSpellChecker = objSC;


}






public ArrayList <typos> CheckSpellings()


{


return objSpellChecker.CheckSpelling();


}


}

这样,在创建文本编辑器时,调用代码可以将适当的 SpellChecker Type 注入到 TextEditor 的实例中。

您可以阅读完整的文章 给你

IOC 是一种让别人为你创建对象的技术。 在春天的情况下,另一个人是 IOC 集装箱。

依赖注入是一种技术,其中一个对象提供另一个对象的依赖关系。

简而言之。

  • IOC (控制反转)这个概念的意思是: 不要使用 new 操作符创建对象,让容器代劳。
  • DI (依赖注入)是通过以下方式注入框架组件的依赖性:
  1. 注射
  2. Setter/Getter 注入
  3. 现场注入

IOC 代表控制反转,是一个更高层次的概念,表明我们将创建对象的控制从调用方转换到被调用方。

如果没有控制反转,你就要负责创造物体。在控制反转场景中,框架负责创建类的实例。

依赖注入是我们达到控制反转的方法。为了让我们将控件留给框架或作业,我们声明了依赖项,IOC 容器在我们的类中注入了这些依赖项(即框架为我们创建了一个实例并提供给我们的类)。

这样做有什么好处?

首先,类及其生命周期将由 Spring 管理。Spring 完全管理从创建到销毁的过程。

其次,您将减少类之间的耦合。一个类不能与另一个类的实现紧密耦合。如果实现发生更改,或者您想要更改注入接口的实现,那么您可以轻松地做到这一点,而无需手动更改代码库中的所有实例。

第三,类之间的内聚性增强。高内聚意味着将彼此关联的类保持在一起。因为我们在其他类中注入接口,所以很清楚哪些类是调用类操作所必需的。

第四,增加了可测试性。因为我们在构造函数中使用接口,所以可以很容易地将实现与模拟实现交换

第五,使用 JDK 动态代理来代理对象。JDK 动态代理要求使用真实的接口,因为我们注入了这些接口。这个代理可以用于 SpringAOP、事务处理、 Spring 数据、 Spring 安全等

Spring 框架可以看作是子框架的集合,也称为层,比如 Spring AOP、 Spring ORM、 Spring Web Flow 和 Spring Web MVC。在构造 Web 应用程序时,可以单独使用这些模块中的任何一个。这些模块也可以组合在一起,以便在 Web 应用程序中提供更好的功能。

在深入到 Spring 到 Container 之前,请记住 Spring 提供了两种类型的 Container,即:

  1. 豆厂容器
  2. ApplicationContext 容器

Spring 框架(如 IoC、 AOP 和事务管理)的特性使其在框架列表中独一无二。Spring 框架的一些最重要的特性如下:

  1. 物联网集装箱
  2. 资料存取架构
  3. 春季 MVC
  4. 交易管理
  5. SpringWebServices
  6. JDBC 抽象层
  7. Spring TestContext 框架

SpringIoC 容器是 SpringFramework 的核心。它创建对象,配置和组装它们的依赖项,管理它们的整个生命周期。Container 使用依赖注入(DI)来管理组成应用程序的组件。它从配置文件(XML)、 Java 代码或 Java 注释和 JavaPOJO 类中获取有关对象的信息。这些对象称为 Beans。由于 Java 对象的控制和它们的生命周期不是由开发人员完成的,因此这个名字有控制反转。