例如:假设我们有一个Employee
对象,并且它依赖于Address
对象。我们将定义一个与Employee
相对应的bean,以定义其对Address
对象的依赖关系。
当Spring尝试创建Employee
对象时,它将看到Employee
依赖于Address
,因此它将首先创建Address
对象(依赖对象),然后将其注入到Employee
对象中。
控制反转(IoC)和依赖注入(DI)可互换使用。通过DI实现IoC,DI是提供依赖项的过程,而IoC是DI的最终结果。(注意: DI不是实现IoC的唯一方式,还有其他方法。)
通过DI,创建对象的责任从我们的应用程序代码转移到Spring容器;这种现象称为IoC。
我将写下我对这两个术语的简单理解:(为了快速理解,只需阅读示例)
依赖注入(DI):
依赖注入通常意味着将一个依赖对象作为参数传递给一个方法,而不是让该方法创建依赖对象。
实际上,这意味着该方法没有直接依赖于特定的实现;满足要求的任何实现都可以作为参数传递。
通过这种实现对象定义它们的依赖关系。Spring 使其可用。这导致了松耦合的应用程序开发。
快速示例:当创建 EMPLOYEE 对象时,如果 ADDRESS 对象被定义为 EMPLOYEE 对象的依赖项,则会自动创建 ADDRESS 对象。
控制反转(IoC)容器:
这是框架的共同特性,IoC 管理 Java 对象。
- 从实例化到销毁,都通过其 BeanFactory 进行管理。
- 被 IoC 容器实例化的 Java 组件称为 bean,并且 IoC 容器管理 bean 的范围、生命周期事件和任何已被配置和编码的 AOP 特性。快速示例:控制反转是关于获得自由、更灵活和更少依赖的。当您使用台式计算机时,您是被奴役的(或者说,受到控制)。您必须坐在屏幕前并看着它。使用键盘输入和鼠标导航。糟糕编写的软件甚至可能让您更受控制。如果您用笔记本电脑替换台式计算机,则可以在某种程度上反转控制。您可以轻松携带它并移动它。因此,现在您可以控制您与计算机的位置,而不是计算机控制它
.
通过实现控制反转,软件/对象消费者可以获得更多对软件/对象的控制/选项,而不是被控制或拥有较少的选项。
控制反转作为设计准则具有以下目的:
- 执行某个任务的执行与实现解耦。
- 每个模块都可以专注于其设计目的。
- 模块不对其他系统做出任何假设,而是依赖于它们的合同。
- 替换模块对其他模块没有副作用。
控制反转 - 意味着将创建和实例化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();
}
}
考虑 Address 类
class Address {
private String street;
private String city;
Address() {
street="test";
city="test1";
}
}
在上述代码中,地址类的值仅在实例化Employee类时设置,这是Address类对Employee类的依赖。Spring使用依赖注入概念解决了这个问题,提供了两种注入依赖的方式。
在Employee类中设置一个接收Address类引用的Setter方法。
public void setAddress(Address addr) {
this.address = addr;
}
Employee类中的构造函数接受Address参数。
Employee(Address addr) {
this.address = addr;
}
通过使用setter/constructor注入,可以独立设置Address类的值。
在Spring中,对象是松耦合的,即每个类都是独立的,因此一切都可以单独进行测试。但是,在使用这些类时,一个类可能依赖其他需要先实例化的类。
因此,我们告诉Spring类A依赖于类B。因此,在为类A创建bean(像类一样)时,它先实例化类B,然后使用setter或constructor DI方法将其注入类A。也就是说,我们在运行时告诉了Spring依赖关系。这就是DI。
由于我们将创建对象(bean)、维护它们及其聚合的责任交给了Spring而不是硬编码,因此我们称其为控制反转(IOC)。
控制反转(IoC):
IoC是一种设计模式,它描述了在系统中反转控制流,使得执行流程不受中央代码的控制。这意味着组件只应该依赖于其他组件的抽象,并且不负责处理依赖对象的创建。而是通过依赖注入(DI),由IoC容器在运行时提供对象实例。
IoC可以促进更好的软件设计,以实现组件的重用、松散耦合和易于测试。
依赖注入(DI):
DI是一种将依赖项传递到对象构造函数的技术。如果对象已从容器加载,则其依赖项将自动由容器提供。这允许您消费依赖项,而无需手动创建实例。这减少了耦合并使您对对象实例的生命周期具有更大的控制。
Spring: Spring是Java平台上的“控制反转”容器。
控制反转(IoC):控制反转(IoC)是面向对象编程的一种实践,通过一个“组装器”对象在运行时绑定对象耦合,在编译时通常无法通过静态分析知道这些信息。
依赖注入(DI):“依赖注入是一种软件设计模式,可以消除硬编码的依赖关系,并使其能够在运行时或编译时更改。”-维基百科。
简单来说..
控制反转是软件架构的一种通用设计原则,有助于创建易于维护的可重用、模块化软件框架。
它是一种设计原则,在其中流程控制“接收”自通用编写的库或可重用代码。
为了更好地理解它,让我们看看我们在编码的早期如何编码。在过程/传统语言中,业务逻辑通常控制应用程序的流程并“调用”通用或可重用的代码/函数。例如,在简单的控制台应用程序中,我的控制流由我的程序指令控制,这可能包括对一些通用可重用函数的调用。
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
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;
}
}
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.
}
}
Class TextEditor
{
ISpellChecker objSpellChecker;
string Text;
public void TextEditor(ISpellChecker objSC)
{
objSpellChecker = objSC;
}
public ArrayList <typos> CheckSpellings()
{
return objSpellChecker.CheckSpelling();
}
}
这样,在创建文本编辑器时,调用代码可以向TextEditor实例注入适当的SpellChecker类型。
您可以在这里阅读完整的文章。
IOC是一种技术,你可以让别人为你创建对象。在Spring的情况下,这个“别人”就是IOC容器。
依赖注入是一种技术,其中一个对象提供另一个对象的依赖项。
IOC代表控制反转,是一个更高级别的概念,它表示我们将对象的创建控制从调用者转移到被调用者。
没有控制反转,你需要负责对象的创建。在控制反转情况下,框架负责创建类的实例。
依赖注入是实现控制反转的方法。为了将控制权留给框架或任务,我们声明依赖关系,IOC容器将这些依赖项注入到我们的类中(即框架为我们创建一个实例并提供给我们的类)。
那么这有什么优势呢?
首先,Spring会管理类及其生命周期。Spring完全管理从创建到销毁的过程。
其次,类之间的耦合度降低。一个类不与另一个类的实现紧密耦合。如果实现发生变化,或者您想要更改注入接口的实现,可以轻松地在代码库中不需要手动更改所有实例。
第三,类之间的内聚性增强。高内聚意味着将相关的类一起保持在一起。因为我们在其他类中注入接口,所以清楚哪些类对于调用类的操作是必要的。
第四,可测试性增强。因为我们在构造函数中使用接口,所以可以轻松地将实现与模拟实现交换。
第五,使用JDK动态代理代理对象。JDK动态代理需要使用接口,这是正确的,因为我们正在注入这些接口。然后可以将此代理用于Spring AOP、事务处理、Spring数据、Spring安全等。