135

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

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

4

12 回答 12

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

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

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

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

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

  • 依赖注入可以通过setter注入或构造函数注入来完成。
于 2014-01-23T10:17:19.463 回答
35

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

  • 依赖注入(DI):
    依赖注入通常意味着将依赖对象作为参数传递给方法,而不是让方法创建依赖对象
    这在实践中意味着该方法不直接依赖于特定的实现;任何满足要求的实现都可以作为参数传递。

    对象的这种实现定义了它们的依赖关系。春天使它可用。
    这导致松散耦合的应用程序开发。

    快速示例:创建员工对象时,它将自动创建地址对象(如果地址被定义为员工对象的依赖项)*。

  • 控制反转(IoC)容器:
    这是框架的共同特征,IoC 通过其 BeanFactory管理 Java 对象- 从实例化到销毁。 - 由 IoC 容器实例化的 Java 组件称为 bean,IoC 容器管理 bean 的范围、生命周期事件以及已为其配置和编码的任何 AOP 功能。. 通过实施控制反转,软件/对象消费者可以获得对软件/对象的更多控制/选项,而不是被控制或拥有更少的选项。作为设计指南的控制反转服务于以下目的: - 将特定任务的执行与实现脱钩。



    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





    - 每个模块都可以专注于它的设计目的。
    - 模块不对其他系统做什么做任何假设,而是依赖于他们的合同。
    - 更换模块对其他模块没有副作用

我将在这里保持抽象,您可以访问以下链接以详细了解该主题。

一个很好的例子

详细解释

于 2014-11-10T08:33:18.743 回答
13

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

所以,我们告诉 spring 类 A 依赖于类 B。因此,当为类 A 创建 bean(如类)时,它在类 A 之前实例化类 B,并使用 setter 或构造函数 DI 方法将其注入到类 A 中。即,我们在运行时告诉 spring 依赖项。这是DI。

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

于 2017-04-27T07:07:21.557 回答
11

控制反转——这意味着将创建和实例化 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. 构造函数注入

Employee 类中接受地址的构造函数

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

通过这种方式,可以使用 setter/constructor 注入独立地设置 Address 类的值。

于 2018-06-27T07:24:01.470 回答
10

控制反转(IOC):

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

IoC 可以实现更好的软件设计,从而促进软件组件的重用、松散耦合和轻松测试。

依赖注入(DI):

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

点击查看更多

于 2017-10-10T11:35:00.137 回答
8

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

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

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

于 2016-02-16T19:34:30.710 回答
6

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

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

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

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,框架是“调用”业务逻辑的可重用代码。

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

虽然,框架的代码不知道我的业务逻辑,但它仍然知道如何调用我的代码。这是使用事件/委托、回调等来实现的。这里的流控制是“反转的”。

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

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

简而言之,当您尝试编写代码时,您将创建和使用不同的类。一类(A 类)可以使用其他类(B 类和/或 D 类)。因此,B 类和 D 类是 A 类的依赖项。

一个简单的类比是 Car 类。一辆车可能依赖于其他类别,如发动机、轮胎等。

依赖注入建议不是依赖类(此处为类 Car)创建其依赖项(类引擎和类 Tyre),而是应该用依赖项的具体实例注入类。

让我们用一个更实际的例子来理解。假设您正在编写自己的 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 的实例中。

你可以在这里阅读完整的文章

于 2018-07-16T12:26:36.887 回答
6

简单来说..

  • IOC(Inversion of Control) 是一个概念,意思是:与其用 new 操作符创建对象,不如让容器为你做。
  • DI(Dependency injection)是通过spring的以下方式注入框架组件的依赖的方式:
  1. 构造器注入
  2. Setter/Getter 注入
  3. 场注入
于 2020-08-24T05:46:54.897 回答
4

IOC 是一种让其他人为您创建对象的技术。在春天的情况下,其他人是 IOC 容器。

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

于 2019-07-28T18:08:57.040 回答
3

IOC 代表控制反转,是一个更高级别的概念,它指出我们将对象创建的控制从调用者反转到被调用者。

在没有控制反转的情况下,您负责对象的创建。在控制反转场景中,框架负责创建类的实例。

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

现在这样做有什么好处?

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

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

第三,阶级之间的凝聚力增强。高内聚意味着将彼此关联的类保持在一起。因为我们在其他类中注入接口,所以很清楚调用类需要哪些类才能运行。

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

五、使用JDK动态代理来代理对象。JDK 动态代理需要使用接口,这是真的,因为我们正在注入这些接口。然后这个代理可以用于 Spring AOP、事务处理、Spring 数据、Spring 安全等

于 2020-08-25T14:33:24.273 回答
2

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

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

于 2017-01-23T12:34:57.620 回答
1

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

在深入了解 Spring 到容器之前,请记住 Spring 提供了两种类型的容器,如下所示:

  1. BeanFactory 容器
  2. 应用上下文容器

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

  1. IoC 容器
  2. 数据访问框架
  3. 春季MVC
  4. 事务管理
  5. 春季网络服务
  6. JDBC 抽象层
  7. Spring TestContext 框架

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

于 2021-11-16T09:56:46.170 回答