Spring框架中IoC容器与DI依赖注入教程

目录
  • 一、Spring 是什么
    • 1.1 什么是容器
    • 1.2 什么是 IoC
  • 二、理解 IoC
    • 2.1 传统程序开发的问题
    • 2.2 分析
    • 2.3 控制反转式程序开发
    • 2.4 对比总结规律
    • 2.5 理解 Spring IoC
  • 三、DI 概念说明
  • 四、总结

一、Spring 是什么

我们通常所说的 Spring 指的是 Spring Framework (Spring 框架),它是⼀个开源框架,有着活跃而庞大的社区,这就是它之所以能长久不衰的原因。Spring ⽀持⼴泛的应⽤场景,它可以让 Java 企业级的应用程序开发起来更简单。

⽤⼀句话概括 Spring:Spring 是包含了众多工具方法的 IoC 容器。

那么问题来了,什么是容器?什么又是 IoC 容器呢?

1.1 什么是容器

顾名思义,容器是用来容纳某种物品的。

我们接触过的容器都有哪些?

  • List/Map -> 数据存储容器
  • Tomcat -> Web 容器

1.2 什么是 IoC

IoC = Inversion of Control 翻译成中⽂是 “控制(权)反转” 的意思,也就是说 Spring 是⼀个 “控制反转” 的容器。怎么理解这句话呢?我们先从以下示例开始 ~

二、理解 IoC

2.1 传统程序开发的问题

假如,我们现在构建⼀辆 “车” 的程序,我们的实现思路是这样的:

构建⼀辆车 (Car Class),然而车需要依赖车身 (FrameWork Class),而车身需要依赖底盘 (Bottom Class),而底盘需要依赖轮胎 (Tire Class),最终程序的实现代码如下:(轮胎只有一个 size 属性)

package old;
/**
 * 构建“车”
 */
public class Car {
    private Framework framework;
    public Car(int size) {
        framework = new Framework(size);
    }
    public static void main(String[] args) {
        int size = 15;
        // 构建并运行车
        Car car = new Car(size);
        car.init();
    }
    // 运行
    public void init() {
        System.out.println("Car init.");
        // 依赖 framework init() 方法
        framework.init();
    }
}
package old;
/**
 * 车身
 */
public class Framework {
    private Bottom bottom;
    public Framework(int size) {
        bottom = new Bottom(size);
    }
    public void init() {
        System.out.println("Framework init.");
        // 依赖 Bottom:init()
        bottom.init();
    }
}
package old;
/**
 * 底盘
 */
public class Bottom {
    private Tire tire;
    public Bottom(int size) {
        tire = new Tire(size); // 自己(创)造
    }
    public void init() {
        System.out.println("Bottom init.");
        // 依赖:Tire:init()
        tire.init();
    }
}
package old;
/**
 * 轮胎
 */
public class Tire {
    // 尺寸
    private int size = 17;
    // 材质...
    // 花纹...
    // 颜色...
    // ...
    public Tire(int size) {
        this.size = size;
    }
    public void init() {
        System.out.println("Tire size:" + size);
    }
}

以上程序中,轮胎属性信息只有 size,然而随着对车的需求量越来越大,个性化需求也会越来越多,这时候我们就需要加工具有多个属性的轮胎。

而以上程序的问题是:添加轮胎属性时,即最底层代码改动之后,整个调用链上的所有代码 (所有类) 都需要修改。

2.2 分析

如何解决上述问题呢?

我们可以尝试不在每个类中自己创建下级类,如果自己创建下级类就会出现当下级类发生改变操作,自己也要跟着修改。

我们只需要将原来由自己创建的下级类,改为传递的方式 (也就是注入的方式),因为我们不需要在当前类中创建下级类了,所以下级类即使发生变化 (创建或减少参数),当前类本身也无需修改任何代码,这样就完成了程序的解耦。

解耦指的是解决了代码的耦合性问题,耦合性换⼀种叫法为程序相关性。好的程序代码的耦合性 (代码之间的相关性) 是很低的 ~~

这就好比我们打造⼀辆完整的汽车,如果所有的配件都是自己造,那么当客户需求发⽣改变的时候,我们就要自己动手来改了;但如果我们是把轮胎外包出去,那么我们只需要向代理工厂下订单就行了,我们自身是不需要出力的。

2.3 控制反转式程序开发

基于以上思路,我们把调用汽车的程序示例改造⼀下,把创建子类的方式,改为注入传递的方式,具体实现代码如下:

package v2;
public class TireV2 {
    private int size = 17;
    private String color = "黑色";
    public TireV2(int size, String color) {
        this.size = size;
        this.color = color;
    }
    public void init() {
        System.out.println("Tire v2 size:" + size);
    }
}
package v2;
public class BottomV2 {
    private TireV2 tireV2;
    public BottomV2(TireV2 tireV2) {
        this.tireV2 = tireV2;
    }
    public void init() {
        System.out.println("Bottom v2 init.");
        tireV2.init();
    }
}
package v2;
public class FrameworkV2 {
    private BottomV2 bottomV2;
    public FrameworkV2(BottomV2 bottomV2) {
        this.bottomV2 = bottomV2;
    }
    public void init() {
        System.out.println("Framework v2 init.");
        bottomV2.init();
    }
}
package v2;
/**
 * 控制反转的车
 */
public class CarV2 {
    private FrameworkV2 frameworkV2; // 依赖
    public CarV2(FrameworkV2 frameworkV2) {
//        frameworkV2 = new FrameworkV2(); // 自己创建(自己控制对象的生命周期)
        this.frameworkV2 = frameworkV2; // Car 构造方法不会在创建
    }
    public void init() {
        System.out.println("Car v2 init.");
        // 依赖 framework:init()
        frameworkV2.init();
    }
}

启动类:

package v2;
public class App {
    public static void main(String[] args) {
        // 程序调用
        int size = 15;
        String color = "红色";
        TireV2 tireV2 = new TireV2(size, color);
        BottomV2 bottomV2 = new BottomV2(tireV2);
        FrameworkV2 frameworkV2 = new FrameworkV2(bottomV2);
        CarV2 carV2 = new CarV2(frameworkV2);
        carV2.init();
    }
}

代码经过以上调整,无论底层类如何变化,整个调用链是不用做任何改变的。这样就完成了代码之间的解耦,从而实现了更加灵活、通用的程序设计!

2.4 对比总结规律

在传统的代码中对象创建顺序是:Car -> Framework -> Bottom -> Tire

改进之后解耦的代码的对象创建顺序是:Tire -> Bottom -> Framework -> Car

传统代码是 Car 创建并控制了 Framework,Framework 创建并控制了 Bottom,依次往下…而改进之后的控制权发生了反转,不再是上级对象创建并控制下级对象了,而是下级对象注入当前对象中,下级不再由上级类控制了!这样即使下级类发生任何改变,当前类都是不受影响的,这就是典型的控制反转,也就是 IoC 的实现思想。

谁调用我,就把控制权交给谁!而不是自己来控制,不用自己去new对象

2.5 理解 Spring IoC

回到我们的主题 Spring,本⽂刚开始咱们就讲:Spring 是包含了多个工具方法的 IoC 容器,这就是对 Spring 最核心的总结。“集成多个工具方法”这事咱们以后慢慢再谈,那如何理解“Spring 是⼀个 IoC 容器”这句话呢?

既然 Spring 是⼀个 IoC(控制反转)容器,重点还在“容器”⼆字上,那么它就具备两个最基础的功能:

  • 将对象存入到容器
  • 从容器中取出对象

也就是说 学习 Spring 最核心的功能,就是学习将对象存入到 Spring 中,再从 Spring 中获取对象的过程 ~

将对象存放到容器中的好处:将对象存储在 IoC 容器相当于将以后可能用到的所有工具都制作好并放到仓库中,需要的时候直接取就行了,用完再把它放回到仓库。而 new 对象的方式相当于,每次需要工具了,才现做,用完就扔掉了也不会保存,下次再用的时候还得重新做,这就是 IoC 容器和普通程序开发的区别。

Spring 是⼀个 IoC 容器,即 对象创建和销毁的权利都交给 Spring 来管理了,它本身又具备了存储对象和获取对象的能力。

三、DI 概念说明

谈到 IoC,不得不提的⼀个词就是 “DI”,DI 是 Dependency Injection 的缩写,翻译成中⽂是 “依赖注入” 的意思。

所谓依赖注入,就是由 IoC 容器在运行期间,动态地将某种依赖关系注入到对象之中。 所以,依赖注入(DI)和控制反转(IoC)是从不同的角度的描述的同⼀件事情,就是指通过引入 IoC 容器,利用依赖关系注⼊的方式,实现对象之间的解耦。

IoC 是“目标”也是⼀种思想,而目标和思想只是⼀种指导原则,最终还是要有可行的落地⽅案,而 DI 就属于具体的实现。

比如说我今天心情比较好,要吃一顿好的犒劳犒劳自己,那么“吃⼀顿好的”是思想和目标 (是 IoC),但最后我是吃海底捞还是必胜客…?这就是具体的实现,就是 DI 。

四、总结

Ioc全称Inversion of Control,把创建对象的权利交给容器,对象的实例不再由调用者来创建,而是由容器来创建,容器会负责控制程序之间的关系,而不是由调用者的程序代码直接控制。这样,控制权由应用代码转移带了容器,控制权发生了反转,这就是控制反转。它是spring框架的核心思想之一。

DI全称Dependency Injection,当某个java 实例需要另一个java实例时,创建被调用者的工作不是由调用者实现,而是由spring容器来完成,然后注入调用者,因此称为依赖注入。

到此这篇关于Spring框架中IoC容器与DI依赖注入教程的文章就介绍到这了,更多相关Spring IoC与DI内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • 新手了解java IO基础知识(二)

    目录 一.IO概念 1.什么是输入 2.什么输出(Output) 二.流的分类 1.InputStream(字节流) 2.OutputStream(字节流) 3.Reader(字符流) 4.Writer(字符流) 三.总结(1+2) 1. File类及方法的使用 2.IO流的分类 3.IO流的四个基本类 总结 一.IO概念 I/O 即输入Input/ 输出Output的缩写,其实就是计算机调度把各个存储中(包括内存和外部存储)的数据写入写出 java中用"流(stream)"来抽象表示

  • Spring IOC与DI核心深入理解

    目录 深入理解IOC思想 DI&IOC 深入理解IOC思想 spring本质就在于将对象全部交由给spring容器创建和管理,由容器控制对象的整个生命周期.核心就是IOC控制反转和AOP面向切面编程 先说IOC IOC是一种设计思想,叫做控制反转.本质就是通过Spring来负责对象的生命周期以及对象间的关系.在面向对象的开发过程中,我们程序中的各个对象往往会存在各种各样的依赖关系,因此耦合度极高,一旦修改其中一个类信息就会牵扯到很多相关类需要修改.那么为了降低这种耦合度IOC指出引用第三方容器,

  • Spring IOC推导与DI构造器注入超详细讲解

    目录 了解准备 IOC思想 IOC本质 XML配置Spring IOC创建对象方式 了解准备 什么是Spring? Spring是一款轻量级的控制反转(IOC)和面向切面编程(AOP)的非入侵式开源框架 2002年Spring的前身interface21发布,随后在2004年3月24日正式更名发布Spring1.0版本 Spring Frameword缔造者 Rod Johnson,悉尼大学音乐学博士生 Spring框架主要由七部分组成,分别是 Spring Core. Spring AOP.

  • Spring框架中IoC容器与DI依赖注入教程

    目录 一.Spring 是什么 1.1 什么是容器 1.2 什么是 IoC 二.理解 IoC 2.1 传统程序开发的问题 2.2 分析 2.3 控制反转式程序开发 2.4 对比总结规律 2.5 理解 Spring IoC 三.DI 概念说明 四.总结 一.Spring 是什么 我们通常所说的 Spring 指的是 Spring Framework (Spring 框架),它是⼀个开源框架,有着活跃而庞大的社区,这就是它之所以能长久不衰的原因.Spring ⽀持⼴泛的应⽤场景,它可以让 Java

  • 浅析Java的Spring框架中IOC容器容器的应用

    Spring容器是Spring框架的核心.容器将创建对象,它们连接在一起,配置它们,并从创建到销毁管理他们的整个生命周期.在Spring容器使用依赖注入(DI)来管理组成应用程序的组件.这些对象被称为Spring Beans. 容器获得其上的哪些对象进行实例化,配置和组装通过阅读提供的配置元数据的说明.配置元数据可以通过XML,Java注释或Java代码来表示.下面的图是Spring如何工作的高层次图. Spring IoC容器是利用Java的POJO类和配置元数据的产生完全配置和可执行的系统或

  • 实例讲解Java的Spring框架中的控制反转和依赖注入

    近来总是接触到 IoC(Inversion of Control,控制反转).DI(Dependency Injection,依赖注入)等编程原则或者模式,而这些是著名 Java 框架 Spring.Struts 等的核心所在.针对此查了 Wikipedia 中各个条目,并从图书馆借来相关书籍,阅读后有些理解,现结合书中的讲解以及自己的加工整理如下: eg1 问题描述: 开发一个能够按照不同要求生成Excel或 PDF 格式的报表的系统,例如日报表.月报表等等.   解决方案: 根据"面向接口编

  • .NET Core使用Autofac容器的DI依赖注入,IOC控制反转及AOP切面编程

    目录 Autofac 容器 Autofac 多种注入方式 Autofac 生命周期 Autofac 支持配置文件 Autofac 整合 .NET 5 MVC Autofac 支持控制器属性注入 Autofac 单实例多实现 Autofac 支持 AOP Autofac 容器 Autofac 是一款.NET IoC 容器 . 它管理类之间的依赖关系, 从而使 应用在规模及复杂性增长的情况下依然可以轻易地修改 . 它的实现方式是将常规的.net类当做组件处理. 安装 NuGet 程序包: Autof

  • laravel框架中你所用到的依赖注入详解

    前言 用Laravel开发前前后后有2个月左右了,之前一直写Java,就像找到Java和PHP之前的共同点,用Java的某些原理去理解PHP会发现还是有很多共通之处的.Java的依赖注入已经是一个很常见的概念了,Spring框架主要就是解决了这一点,在PHP的laravel框架中,也出现了依赖注入的方式. 依赖注入就控制反转的一种是实现方式,面向对象的特征的重要体现,那么依赖注入中什么是依赖呢,这点用Java开发的人很多都能理解.笼统的说依赖就是一种联系,变量和实现的联系.有关于依赖注入的理解之

  • 详谈spring boot中几种常见的依赖注入问题

    目录 @Autowired依赖注入问题–逻辑使用先于@Autowired注解处理 测试用例 BeanFactory.getBean问题–getBean调用先于BeanDefinition信息注册 在Configuration中使用@Autowired注解 spring 实例化Bean过程 @Bean内部使用配置类@Autowired注解引入依赖 InitializingBean#afterPropertiesSet内部使用依赖 总结 最近有空总结一下之前在使用spring boot时遇到过的几种

  • .net程序开发IOC控制反转和DI依赖注入详解

    目录 IOC控制反转 DI依赖注入 服务生命周期 其它 IOC控制反转 大部分应用程序都是这样编写的:编译时依赖关系顺着运行时执行的方向流动,从而生成一个直接依赖项关系图. 也就是说,如果类 A 调用类 B 的方法,类 B 调用 C 类的方法,则在编译时,类 A 将取决于类 B,而 B 类又取决于类 C 应用程序中的依赖关系方向应该是抽象的方向,而不是实现详细信息的方向.而这就是控制反转的思想. 应用依赖关系反转原则后,A 可以调用 B 实现的抽象上的方法,让 A 可以在运行时调用 B,而 B

  • 深入理解Java的Spring框架中的IOC容器

    Spring IOC的原型 spring框架的基础核心和起点毫无疑问就是IOC,IOC作为spring容器提供的核心技术,成功完成了依赖的反转:从主类的对依赖的主动管理反转为了spring容器对依赖的全局控制. 这样做的好处是什么呢? 当然就是所谓的"解耦"了,可以使得程序的各模块之间的关系更为独立,只需要spring控制这些模块之间的依赖关系并在容器启动和初始化的过程中将依据这些依赖关系创建.管理和维护这些模块就好,如果需要改变模块间的依赖关系的话,甚至都不需要改变程序代码,只需要将

  • 深入浅出讲解Spring框架中依赖注入与控制反转及应用

    目录 一. 概念: 1. 使用前: 2. 使用后: 二. 理解控制反转(Ioc): 三. IoC的应用方法 一. 概念: 依赖注入(Dependency Injection,DI)与控制反转(IoC)的含义相同,只不过是从两个角度描述的同一个概念.对于一个Spring初学者来说,这两种称呼都很难理解,我们通过简单的语言来描述这两个概念. 使用对比: 1. 使用前: 当某个Java对象(调用者)需要调用另一个Java对象(被调用者,就是被依赖对象)时,在传统模式下,调用者通常会采用"new被调用者

  • 浅谈spring DI 依赖注入方式和区别

    目录 spring DI 3种DI注解的区别 1 @Autowired 2 @Inject 3 @Resource 3种注入方式的区别 1 field注入 2 构造器注入 3 setter注入 构造器注入的好处 1 依赖不可变 2 依赖不为空 3 完全初始化状态 4 避免循环依赖 5 总结 spring DI Spring框架对Java开发的重要性不言而喻,其核心特性就是IOC(Inversion of Control, 控制反转)和AOP,平时使用最多的就是其中的IOC,我们通过将组件交由Sp

随机推荐