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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/9403155/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-08 04:57:36  来源:igfitidea点击:

What is Dependency Injection and Inversion of Control in Spring Framework?

springdependenciescontrolscode-injectioninversion

提问by Chillax

"Dependency Injection" and "Inversion of Control" are often mentioned as the primary advantages of using the Spring framework for developing Web frameworks

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

Could anyone explain what it is in very simple terms with an example if possible?

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

回答by Krishnakant Kadam

  • Spring helps in the creation of loosely coupled applications because of Dependency Injection.
  • In Spring, objects define their associations (dependencies) and do not worry about how they will get those dependencies. It is the responsibility of Spring to provide the required dependencies for creating objects.
  • 由于依赖注入,Spring 有助于创建松散耦合的应用程序。
  • 在 Spring 中,对象定义了它们的关联(依赖项)并且不用担心它们将如何获得这些依赖项。Spring 负责提供创建对象所需的依赖项。

For example: Suppose we have an object Employeeand it has a dependency on object Address. We would define a bean corresponding to Employeethat will define its dependency on object Address.

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

When Spring tries to create an Employeeobject, it will see that Employeehas a dependency on Address, so it will first create the Addressobject (dependent object) and then inject it into the Employeeobject.

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

  • Inversion of Control (IoC) and Dependency Injection (DI) are used interchangeably. IoC is achieved through DI. DI is the process of providing the dependencies and IoC is the end result of DI. (Note:DI is not the only way to achieve IoC. There are other waysas well.)

  • By DI, the responsibility of creating objects is shifted from our application code to the Spring container; this phenomenon is called IoC.

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

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

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

回答by VdeX

I shall write down my simple understanding of this two terms:(For quick understanding just read examples)

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

  • Dependency Injection(DI):
    Dependency injection generally means passing a dependent object as a parameter to a method, rather than having the method create the dependent object.
    What it means in practice is that the method does not have a direct dependency on a particular implementation; any implementation that meets the requirements can be passed as a parameter.

    With this implementation of objects defines their dependencies. And spring makes it available.
    This leads to loosely coupled application development.

    Quick Example:EMPLOYEE OBJECT WHEN CREATED,IT WILL AUTOMATICALLY CREATE ADDRESS OBJECT (if address is defines as dependency by Employee object)*.

  • Inversion of Control(IoC) Container:
    This is common characteristic of frameworks, IoC manages java objects
    - from instantiation to destruction through its BeanFactory.
    - Java components that are instantiated by the IoC container are called beans, and the IoC container manages a bean's scope, lifecycle events, and any AOP featuresfor which it has been configured and coded.

    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.

    By implementing Inversion of Control, a software/object consumer get more controls/options over the software/objects, instead of being controlled or having less options.

    Inversion of control as a design guideline serves the following purposes:
    - There is a decoupling of the execution of a certain task from implementation.
    - Every module can focus on what it is designed for.
    - Modules make no assumptions about what other systems do but rely on their contracts.
    - Replacing modules has no side effect on other modules

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

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

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

  • 控制反转(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.

    通过实施控制反转,软件/对象消费者获得对软件/对象的更多控制/选项,而不是被控制或拥有更少的选项。

    作为设计指南的控制反转有以下目的:
    - 将某个任务的执行与实现分离。
    - 每个模块都可以专注于它的设计目的。
    - 模块不对其他系统做什么做任何假设,而是依赖于它们的契约。
    - 更换模块对其他模块没有副作用

I will keep things abstract here, you can visit following links for detail understanding of the topic.

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

A good read with example

一个很好的例子阅读

Detailed explanation

详细说明

回答by Venkateswara Rao

In Spring Objects are loosely coupled i.e., each class is independent of each other so that everything can be tested individually. But when using those classes, a class may be dependent on other classes which need to be instantiated first.

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

So, we tell spring that class A is dependent on class B. So, when creating bean(like class) for class A, it instantiates class B prior to that of class A and injects that in class A using setter or constructor DI methods. I.e., we are telling spring the dependency at run-time. This is DI.

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

As, we are assigning the responsibility of creating objects(beans), maintaining them and their aggregations to Spring instead of hard-coding it, we call it Inversion Of Control(IOC).

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

回答by Greesh Kumar

Inversion Of Control (IOC):

控制反转(IOC):

IoCis a design pattern that describes inverting the flow of control in a system, so execution flow is not controlled by a central piece of code. This means that components should only depend on abstractions of other components and are not be responsible for handling the creation of dependent objects. Instead, object instances are supplied at runtime by an IoC container through Dependency Injection (DI).

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

IoC enables better software design that facilitates reuse, loose coupling, and easy testing of software components.

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

Dependency Injection (DI):

依赖注入(DI):

DIis a technique for passing dependencies into an object's constructor. If the object has been loaded from the container, then its dependencies will be automatically supplied by the container. This allows you to consume a dependency without having to manually create an instance. This reduces coupling and gives you greater control over the lifetime of object instances.

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

click to view more

点击查看更多

回答by Nadhu

Spring: Spring is “Inversion of Control” container for the Java Platform.

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

Inversion of Control (IoC): Inversion of Control (IoC) is an object-oriented programing practice whereby the object coupling is bounded at runtime by an "assembler" object and are typically not knowable at compile time using static analysis.

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

Dependency Injection (DI): "Dependency injection is a software design pattern that allows the removal of hard-coded dependencies and makes it possible to change them, whether at run-time or compile-time." -wiki.

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

回答by Hetal Rachh

Inversion of control- It means giving the control of creating and instantiating the spring beans to the Spring IOC container and the only work the developer does is configuring the beans in the spring xml file.

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

Dependency injection-

依赖注入-

Consider a class Employee

考虑一个班级员工

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

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


}

and consider class Address

并考虑类地址

class Address {
   private String street;
   private String city;

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

  }
}

In the above code the address class values will be set only when the Employee class is instantiated, which is dependency of Address class on Employee class. And spring solves this problem using Dependency Injection concept by providing two ways to inject this dependency.

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

  1. Setter injection
  1. 二传手注入

Setter method in Employee class which takes a reference of Address class

Employee 类中的 Setter 方法,它引用了 Address 类

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

Constructor in Employee class which accepts Address

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

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

In this way the Address class values can be set independently using either setter/constructor injection.

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

回答by Amrit

Inversion of Control is a generic design principle of software architecture that assists in creating reusable, modular software frameworks that are easy to maintain.

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

It is a design principle in which the Flow of Control is "received" from the generic-written library or reusable code.

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

To understand it better, lets see how we used to code in our earlier days of coding. In procedural/traditional languages, the business logic generally controls the flow of the application and "Calls" the generic or reusable code/functions. For example, in a simple Console application, my flow of control is controlled by my program's instructions, that may include the calls to some general reusable functions.

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

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

In Contrast, with IoC, the Frameworks are the reusable code that "Calls" the business logic.

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

For example, in a windows based system, a framework will already be available to create UI elements like buttons, menus, windows and dialog boxes. When I write the business logic of my application, it would be framework's events that will call my business logic code (when an event is fired) and NOT the opposite.

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

Although, the framework's code is not aware of my business logic, it will still know how to call my code. This is achieved using events/delegates, callbacks etc. Here the Control of flow is "Inverted".

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

So, instead of depending the flow of control on statically bound objects, the flow depends upon the overall object graph and the relations between different objects.

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

Dependency Injection is a design pattern that implements IoC principle for resolving dependencies of objects.

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

In simpler words, when you are trying to write code, you will be creating and using different classes. One class (Class A) may use other classes (Class B and/or D). So, Class B and D are dependencies of class A.

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

A simple analogy will be a class Car. A car might depend on other classes like Engine, Tyres and more.

一个简单的类比是 Car 类。汽车可能依赖于其他类,如引擎、轮胎等。

Dependency Injection suggests that instead of the Dependent classes (Class Car here) creating its dependencies (Class Engine and class Tyre), class should be injected with the concrete instance of the dependency.

依赖注入建议,而不是依赖类(这里的类 Car)创建它的依赖(类引擎和类 Tyre),类应该注入依赖的具体实例。

Lets understand with a more practical example. Consider that you are writing your own TextEditor. Among other things, you can have a spellchecker that provides the user with a facility to check the typos in his text. A simple implementation of such a code can be:

让我们通过一个更实际的例子来理解。考虑您正在编写自己的文本编辑器。除此之外,您可以拥有一个拼写检查器,为用户提供检查文本中的拼写错误的便利。此类代码的简单实现可以是:

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;

    }

}

At first sight, all looks rosy. The user will write some text. The developer will capture the text and call the CheckSpellings function and will find a list of Typos that he will show to the User.

乍一看,一切都显得红润。用户将编写一些文本。开发人员将捕获文本并调用 CheckSpellings 函数,并将找到他将向用户显示的错字列表。

Everything seems to work great until one fine day when one user starts writing French in the Editor.

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

To provide the support for more languages, we need to have more SpellCheckers. Probably French, German, Spanish etc.

为了提供对更多语言的支持,我们需要有更多的 SpellCheckers。可能是法语、德语、西班牙语等。

Here, we have created a tightly-coupled code with "English"SpellChecker being tightly coupled with our TextEditor class, which means our TextEditor class is dependent on the EnglishSpellChecker or in other words EnglishSpellCheker is the dependency for TextEditor. We need to remove this dependency. Further, Our Text Editor needs a way to hold the concrete reference of any Spell Checker based on developer's discretion at run time.

在这里,我们创建了一个紧密耦合的代码,其中“English”SpellChecker 与我们的 TextEditor 类紧密耦合,这意味着我们的 TextEditor 类依赖于 EnglishSpellChecker,或者换句话说 EnglishSpellCheker 是 TextEditor 的依赖项。我们需要移除这个依赖。此外,我们的文本编辑器需要一种方法来根据开发人员在运行时的判断来保存任何拼写检查器的具体引用。

So, as we saw in the introduction of DI, it suggests that the class should be injected with its dependencies. So, it should be the calling code's responsibility to inject all the dependencies to the called class/code. So we can restructure our code as

因此,正如我们在 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.

    }

}

In our example, the TextEditor class should receive the concrete instance of ISpellChecker type.

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

Now, the dependency can be injected in Constructor, a Public Property or a method.

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

Lets try to change our class using Constructor DI. The changed TextEditor class will look something like:

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

Class TextEditor

{

    ISpellChecker objSpellChecker;

    string Text;



    public void TextEditor(ISpellChecker objSC)

    {

        objSpellChecker = objSC;

    }



    public ArrayList <typos> CheckSpellings()

    {

        return objSpellChecker.CheckSpelling();

    }

}

So that the calling code, while creating the text editor can inject the appropriate SpellChecker Type to the instance of the TextEditor.

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

You can read the complete article here

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

回答by daemon

IOC is technique where you let someone else to create the object for you. And the someone else in case of spring is IOC container.

IOC 是一种技术,您可以让其他人为您创建对象。而春天的另一个人是IOC容器。

Dependency Injection is a technique where one object supplies the dependency of another object.

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

回答by SumataPatil

The traditional way of getting address instance in Employee would be by creating a new instance of Address class.Spring creates all dependent object ton us hence we need not to worry about object.

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

So in Spring we just depend on the spring container which provide us with the dependency object.

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