前言

「上一篇文章」我们对 Spring 有了初步的认识,而 Spring 全家桶中几乎所有组件都是依赖于 IoC 的。

刚开始听到 IoC,会觉得特别高大上,但其实掰开了很简单。

跟着我的脚步,一文带你吃透 IoC 原理。

本文主要讲原理,围绕“是何”、“为何”来谈,下一篇文章会讲实践部分,也就是“如何”。

文本已收录至我的 Github: https://github.com/xiaoqi6666/NYCSDE

是何

上一篇文章有同学问我在官网该看哪些内容,怎么找的,那今天的截图里都会有链接。

初识 IoC

根据上一篇文章我们说的,Spring 全家桶中最重要的几个项目都是基于 Spring Framework 的,所以我们就以 Spring Framework 为例来看文档

首先它的右侧有 Github 的链接,另外点到「LEARN」这里,就会看到各个版本的文档。

那我们点「Reference Doc」,就能够看到它的一些模块的介绍:

(等下... 模块?什么是模块?这个问题下文回答。)

第一章 Overview,讲述它的历史、设计原理等等;

第二章 Core,包含了 IoC 容器,AOP 等等,那自然是讲 Spring 的核心了,要点进去好好看了。

点进去之后发现了宝贵的学习资料,一切的 what, why, how 都可以在这里找到答案。

这里很好的解释了大名鼎鼎的 IoC - Inversion of Control, 控制反转。

每次读都会有新的体会和收获。

我粗略的总结一下:控制反转就是把创建和管理 bean 的过程转移给了第三方。而这个第三方,就是 Spring IoC Container,对于 IoC 来说,最重要的就是容器

容器负责创建、配置和管理 bean,也就是它管理着 bean 的生命,控制着 bean 的依赖注入。

通俗点讲,因为项目中每次创建对象是很麻烦的,所以我们使用 Spring IoC 容器来管理这些对象,需要的时候你就直接用,不用管它是怎么来的、什么时候要销毁,只管用就好了。

举个例子,就好像父母没时间管孩子,就把小朋友交给托管所,就安心的去上班而不用管孩子了。

托儿所,就是第三方容器,负责管理小朋友的吃喝玩乐;

父母,相当于程序员,只管接送孩子,不用管他们吃喝。

等下,bean 又是什么?

Bean 其实就是包装了的 Object,无论是控制反转还是依赖注入,它们的主语都是 object,而 bean 就是由第三方包装好了的 object。(想一下别人送礼物给你的时候都是要包装一下的,自己造的就免了。

IoC 容器

既然说容器是 IoC 最重要的部分,那么 Spring 如何设计容器的呢?

还是回到官网,第二段有介绍哦:

答:使用 ApplicationContext,它是 BeanFactory 的子类,更好的补充并实现了 BeanFactory 的。

BeanFactory 简单粗暴,可以理解为 HashMap:

  • Key - bean name
  • Value - bean object

但它一般只有 get, put 两个功能,所以称之为“低级容器”。

ApplicationContext 多了很多功能,因为它继承了多个接口,可称之为“高级容器”。在下文的搭建项目中,我们会使用它。

ApplicationContext 的里面有两个具体的实现子类,用来读取配置配件的:

  • ClassPathXmlApplicationContext - 从 class path 中加载配置文件,更常用一些;
  • FileSystemXmlApplicationContext - 从本地文件中加载配置文件,不是很常用,如果再到 Linux 环境中,还要改路径,不是很方便。

当我们点开 ClassPathXmlApplicationContext 时,发现它并不是直接继承 ApplicationContext 的,它有很多层的依赖关系,每层的子类都是对父类的补充实现。

而再往上找,发现最上层的 class 回到了 BeanFactory,所以它非常重要。

要注意,Spring 中还有个 FactoryBean,两者并没有特别的关系,只是名字比较接近,所以不要弄混了顺序。

为了好理解 IoC,我们先来回顾一下不用 IoC 时写代码的过程。

深入理解 IoC

这里用经典 class Rectangle 来举例:

  • 两个变量:长和宽
  • 自动生成 set() 方法和 toString() 方法

注意 ️:一定要生成 set() 方法,因为 Spring IoC 就是通过这个 set() 方法注入的;

toString() 方法是为了我们方便打印查看。

public class Rectangle {
private int width;
private int length; public Rectangle() {
System.out.println("Hello World!");
} public void setWidth(int widTth) {
this.width = widTth;
} public void setLength(int length) {
this.length = length;
} @Override
public String toString() {
return "Rectangle{" +
"width=" + width +
", length=" + length +
'}';
}
}

然后在 test 文件中手动用 set() 方法给变量赋值。

嗯,其实这个就是「解藕」的过程!

public class MyTest {
@Test
public void myTest() {
Rectangle rect = new Rectangle();
rect.setLength(2);
rect.setWidth(3);
System.out.println(rect);
}
}

其实这就是 IoC 给属性赋值的实现方法,我们把「创建对象的过程」转移给了 set() 方法,而不是靠自己去 new,就不是自己创建的了。

这里我所说的“自己创建”,指的是直接在对象内部来 new,是程序主动创建对象的正向的过程;

这里使用 set() 方法,是别人(test)给我的;

而 IoC 是用它的容器来创建、管理这些对象的,其实也是用的这个 set() 方法,不信,你把这个这个方法去掉或者改个名字试试?

几个关键问题:

何为控制,控制的是什么?

答:是 bean 的创建、管理的权利,控制 bean 的整个生命周期。

何为反转,反转了什么?

答:把这个权利交给了 Spring 容器,而不是自己去控制,就是反转。

由之前的自己主动创建对象,变成现在被动接收别人给我们的对象的过程,这就是反转。

举个生活中的例子,主动投资和被动投资。

自己炒股、选股票的人就是主动投资,主动权掌握在自己的手中;

而买基金的人就是被动投资,把主动权交给了基金经理,除非你把这个基金卖了,否则具体选哪些投资产品都是基金经理决定的。

依赖注入

回到文档中,第二句话它说:IoC is also known as DI.

我们来谈谈 dependency injection - 依赖注入。

何为依赖,依赖什么?

程序运行需要依赖外部的资源,提供程序内对象的所需要的数据、资源。

何为注入,注入什么?

配置文件把资源从外部注入到内部,容器加载了外部的文件、对象、数据,然后把这些资源注入给程序内的对象,维护了程序内外对象之间的依赖关系。

所以说,控制反转是通过依赖注入实现的。

但是你品,你细品,它们是有差别的,像是「从不同角度描述的同一件事」

  • IoC 是设计思想,DI 是具体的实现方式;
  • IoC 是理论,DI 是实践;

从而实现对象之间的解藕。

当然,IoC 也可以通过其他的方式来实现,而 DI 只是 Spring 的选择。

IoC 和 DI 也并非 Spring 框架提出来的,Spring 只是应用了这个设计思想和理念到自己的框架里去。

为何

那么为什么要用 IoC 这种思想呢?换句话说,IoC 能给我们带来什么好处?

答:解藕。

它把对象之间的依赖关系转成用配置文件来管理,由 Spring IoC Container 来管理。

在项目中,底层的实现都是由很多个对象组成的,对象之间彼此合作实现项目的业务逻辑。但是,很多很多对象紧密结合在一起,一旦有一方出问题了,必然会对其他对象有所影响,所以才有了解藕的这种设计思想。

如上图所示,本来 ABCD 是互相关联在一起的,当加入第三方容器的管理之后,每个对象都和第三方法的 IoC 容器关联,彼此之间不再直接联系在一起了,没有了耦合关系,全部对象都交由容器来控制,降低了这些对象的亲密度,就叫“解藕”。

那么我们下一篇文章就来讲一下如何搭建一个 Spring 项目。

如果你喜欢这篇文章,记得给我点赞留言哦~你们的支持和认可,就是我创作的最大动力,我们下篇文章见!

我是小齐,纽约程序媛,终生学习者,每天晚上 9 点,云自习室里不见不散!

更多干货文章见我的 Github: https://github.com/xiaoqi6666/NYCSDE

Spring IoC 到底是什么的更多相关文章

  1. Spring IoC源码解析——Bean的创建和初始化

    Spring介绍 Spring(http://spring.io/)是一个轻量级的Java 开发框架,同时也是轻量级的IoC和AOP的容器框架,主要是针对JavaBean的生命周期进行管理的轻量级容器 ...

  2. Spring系列之谈谈对Spring IOC的理解

    学习过Spring框架的人一定都会听过Spring的IoC(控制反转) .DI(依赖注入)这两个概念,对于初学Spring的人来说,总觉得IOC .DI这两个概念是模糊不清的,是很难理解的,今天和大家 ...

  3. [Spring框架]Spring IOC的原理及详解。

    这里感谢 CSDN 的原博客:http://blog.csdn.net/m13666368773/article/details/7802126 看后  受益匪浅,这里再重温一遍Spring IOC ...

  4. 走进 Spring IOC 的世界

    转载出自:http://blog.csdn.net/m13666368773/article/details/7802126 1. IoC理论的背景我们都知道,在采用面向对象方法设计的软件系统中,它的 ...

  5. 解读Spring Ioc容器设计图

    在Spring Ioc容器的设计中,有俩个主要的容器系列:一个是实现BeanFactory接口的简单容器系列,这系列容器只实现了容器最基本的功能:另外一个是ApplicationContext应用上下 ...

  6. Spring IOC容器基本原理

    2.2.1 IOC容器的概念IOC容器就是具有依赖注入功能的容器,IOC容器负责实例化.定位.配置应用程序中的对象及建立这些对象间的依赖.应用程序无需直接在代码中new相关的对象,应用程序由IOC容器 ...

  7. 深入理解Spring IOC工作原理

    为什么会出现spring,spring出现解决了什么问题? 1.分析普通多层架构存在的问题 JSP->Servlet->Service->Dao 层与层之间的依赖很强,属于耦合而且是 ...

  8. 1.3浅谈Spring(IOC容器的实现)

    这一节我们来讨论IOC容器到底做了什么. 还是借用之前的那段代码 ClassPathXmlApplicationContext app = new ClassPathXmlApplicationCon ...

  9. Spring Ioc 常用注解

    在开发中spring ioc的配置方式有多种方式,常用的一般都是byName.byType .以及其自动装配可以查看http://www.cnblogs.com/gubai/p/9140840.htm ...

随机推荐

  1. .netcore tif文件转jpg,并通过webapi返回

    网上能搜到很多关于c# tif转jpg的代码.最简单的就是下面这段获得转换后的图片图片对象.在netcore 中使用这段代码时由于netcore框架已经不自带System.Drawing命名空间了所有 ...

  2. 总结关于Ubuntu 安装 Docker 配置相关问题及解决方法

    总结关于Ubuntu 安装 Docker 配置相关问题及解决方法 Tomcat 示例 软件镜像(xx安装程序)----运行镜像----产生一个容器(正在运行的软件,运行的xx): 步骤: 1.搜索镜像 ...

  3. pandas | DataFrame中的排序与汇总方法

    本文始发于个人公众号:TechFlow,原创不易,求个关注 今天是pandas数据处理专题的第六篇文章,我们来聊聊DataFrame的排序与汇总运算. 在上一篇文章当中我们主要介绍了DataFrame ...

  4. Vue Axios 的封装使用

    目录 Axios 说明 安装 Axios 请求配置 响应结构 常用请求方法 默认值配置 全局的 请求配置项 自定义实例默认值 配置的优先顺序 拦截器 个人完整 axios 配置 Axios 说明 Ax ...

  5. 在我们使用Redis作为一个LRU缓存的时候,怎么做才能更高效

    当用Redis作为一个LRU存储时,有些时候是比较方便的,在你增添新的数据时会自动驱逐旧的数据.这种行为在开发者论坛是非常有名的,因为这是流行的memcached系统的默认行为. LRU实际上只是支持 ...

  6. Python 抓包程序(pypcap)

    #/usr/bin/env python #-*-coding:utf8-*- #抓包脚本 """ This script is used to Capture and ...

  7. Go | Go 语言打包静态文件以及如何与Gin一起使用Go-bindata

    系列文章目录 第一章 Go 语言打包静态文件以及如何与Gin一起使用Go-bindata 目录 系列文章目录 前言 一.go-bindata是什么? 二.使用步骤 1. 安装 2. 使用 3. 读取文 ...

  8. 第7篇scrum冲刺(5.27)

    一.站立会议 1.照片 2.工作安排 成员 昨天已完成的工作 今天的工作安排 困难 陈芝敏  学习云开发,云函数调用以及数据的前后端传递  今天实现云词库搭建,随机获取并显示,对云开发有更深的认识   ...

  9. 强化学习模型实现RL-Adventure

    源代码:https://github.com/higgsfield/RL-Adventure 在Pytorch1.4.0上解决bug后的复现版本:https://github.com/lucifer2 ...

  10. SCAFFOLD: Stochastic Controlled Averaging for On-Device Federated Learning

    郑重声明:原文参见标题,如有侵权,请联系作者,将会撤销发布! 以下是对本文关键部分的摘抄翻译,详情请参见原文. arXiv:1910.06378v1 [cs.LG] 14 Oct 2019 Abstr ...