【SpringBoot】 理解Spirng中的IOC原理
前言
前文已经介绍了Spring Bean的生命周期,在这个周期内有一个重要的概念就是: IOC容器
大家也知道IOC是Sping 的重要核心之一,那么如何理解它呢,它又是产生什么作用呢?本文就IOC原理进行简要阐述。
IOC定义
IoC 全称为 Inversion of Control,翻译为 “控制反转”,它还有一个别名为 DI(Dependency Injection),即依赖注入。
DI—Dependency Injection,即“依赖注入”:组件之间依赖关系由容器在运行期决定,形象的说,即由容器动态的将某个依赖关系注入到组件之中。
依赖注入的目的并非为软件系统带来更多功能,而是为了提升组件重用的频率,并为系统搭建一个灵活、可扩展的平台。
通过依赖注入机制,我们只需要通过简单的配置,而无需任何代码就可指定目标需要的资源,完成自身的业务逻辑,而不需要关心具体的资源来自何处,由谁实现。
如何理解“控制反转”好呢?理解好它的关键在于我们需要回答如下四个问题:
- 谁控制谁
- 控制什么
- 为何是反转
- 哪些方面反转了
IoC和DI由什么关系呢?其实它们是同一个概念的不同角度描述,由于控制反转概念比较含糊(可能只是理解为容器控制对象这一个层面,很难让人想到谁来维护对象关系),所以2004年大师级人物Martin Fowler又给出了一个新的名字:“依赖注入”,相对IoC 而言,“依赖注入”明确描述了“被注入对象依赖IoC容器配置依赖对象”。
理解IOC
以年轻小伙子找女朋友为例子来说明IOC的作用:
/**
* 年轻小伙子
*/
public class YoungMan {
private BeautifulGirl beautifulGirl; YoungMan(){
// 可能你比较牛逼,指腹为婚
// beautifulGirl = new BeautifulGirl();
} public void setBeautifulGirl(BeautifulGirl beautifulGirl) {
this.beautifulGirl = beautifulGirl;
} public static void main(String[] args){
YoungMan you = new YoungMan();
BeautifulGirl beautifulGirl = new BeautifulGirl("你的各种条件");
beautifulGirl.setxxx("各种投其所好"); // 然后你有女票了
you.setBeautifulGirl(beautifulGirl);
}
}
不使用IOC:
小伙子需要: new BeautifulGirl() ,也就是自己去创建一个女朋友对象。这个过程复杂而又繁琐,而且我们必须要面对每个环节,同时使用完成之后我们还要负责销毁它。
使用IOC:
小伙子自己不用去找女朋友,反过来找IOC,IOC就相当于一个婚介公司,它管理着很多男男女女的资料,小伙子直接跟婚介公司提出需求,婚介公司则会根据需求提供一个妹子给我们,我们只需要负责使用它就行了。
所以,简单点说,IoC 的理念就是让别人为你服务
可以理解为: IOC主动把妹子注入给想使用它的小伙子。 (调用的时候使用Autowied ,这个对象就是前文说的bean, 通过注册进入IOC容器,被实例化之后再进入IOC容器的bean缓存池,就可以供程序调用了,这就和bean的生命周期连了起来。)
通过IOC的注册机制可以保证对象的安全性和合规性;
实例化对象只需要实例化一次,即可进入IOC容器的bean缓存池,降低了对象的创建开销,提高了程序的性能(有点类似单例);
应用程序调用对象从bean缓存池获取,这样是秒获取对象,提高了调用对象的速度。
现在来回答上面那四个问题,答案就显得非常明显了:
- 谁控制谁:在传统的开发模式下,我们都是采用直接 new 一个对象的方式来创建对象,也就是说你依赖的对象直接由你自己控制,但是有了 IOC 容器后,则直接由 IoC 容器来控制。所以“谁控制谁”,当然是 IoC 容器控制对象。
- 控制什么:控制对象。
- 为何是反转:没有 IoC 的时候我们都是在自己对象中主动去创建被依赖的对象,这是正转。但是有了 IoC 后,所依赖的对象直接由 IoC 容器创建后注入到被注入的对象中,依赖的对象由原来的主动获取变成被动接受,所以是反转。
- 哪些方面反转了:所依赖对象的获取被反转了。
IOC提供被依赖对象的方式
IOC Service Provider 为被注入对象提供被依赖对象也有如下几种方式:构造方法注入、stter方法注入、接口注入。
构造器注入
构造器注入,顾名思义就是被注入的对象通过在其构造方法中声明依赖对象的参数列表,让外部知道它需要哪些依赖对象。
YoungMan(BeautifulGirl beautifulGirl){
this.beautifulGirl = beautifulGirl; //这里可以定义很多女孩的条件
}
构造器注入方式比较直观,对象构造完毕后就可以直接使用,这就好比你出生你家里就给你指定了你媳妇。
setter 方法注入
对于 JavaBean 对象而言,我们一般都是通过 getter 和 setter 方法来访问和设置对象的属性。所以,当前对象只需要为其所依赖的对象提供相对应的 setter 方法,就可以通过该方法将相应的依赖对象设置到被注入对象中。如下:
public class YoungMan {
private BeautifulGirl beautifulGirl;
public void setBeautifulGirl(BeautifulGirl beautifulGirl) {
this.beautifulGirl = beautifulGirl;
}
}
相比于构造器注入,setter 方式注入会显得比较宽松灵活些,它可以在任何时候进行注入(当然是在使用依赖对象之前),这就好比你可以先把自己想要的妹子想好了,然后再跟婚介公司打招呼,你可以要林志玲款式的,赵丽颖款式的,随意性较强。
一般程序中会使用这种方法进行实例化。
接口方式注入
接口方式注入显得比较霸道,因为它需要被依赖的对象实现不必要的接口,带有侵入性。一般都不推荐这种方式。
总结:
A对象需要使用合作对象B来共同完成一件事,A要使用B,那么A就对B产生了依赖,也就是A和B之间存在一种耦合关系,并且是紧密耦合在一起。
而使用了Spring之后就不一样了,创建合作对象B的工作是由Spring来做的,Spring创建好B对象,然后存储到一个容器里面,当A对象需要使用B对象时,Spring就从存放对象的那个容器里面取出A要使用的那个B对象,然后交给A对象使用,至于Spring是如何创建那个对象,以及什么时候创建好对象的,A对象不需要关心这些细节问题(你是什么时候生的,怎么生出来的我可不关心,能帮我干活就行),A得到Spring给我们的对象之后,两个人一起协作完成要完成的工作即可。
所以控制反转IoC(Inversion of Control)是说创建对象的控制权进行转移,以前创建对象的主动权和创建时机是由自己把控的,而现在这种权力转移到第三方,比如转移交给了IoC容器,它就是一个专门用来创建对象的工厂,你要什么对象,它就给你什么对象,有了 IoC容器,依赖关系就变了,原先的依赖关系就没了,它们都依赖IoC容器了,通过IoC容器来建立它们之间的关系。
【SpringBoot】 理解Spirng中的IOC原理的更多相关文章
- 理解Spring中的IoC和DI
什么是IoC和DI IoC(Inversion of Control 控制反转):是一种面向对象编程中的一种设计原则,用来减低计算机代码之间的耦合度.其基本思想是:借助于"第三方" ...
- 深入理解JDK中的Reference原理和源码实现
前提 这篇文章主要基于JDK11的源码和最近翻看的<深入理解Java虚拟机-2nd>一书的部分内容,对JDK11中的Reference(引用)做一些总结.值得注意的是,通过笔者对比一下JD ...
- 理解Spring中的IOC和AOP
我们是在使用Spring框架的过程中,其实就是为了使用IOC,依赖注入和AOP,面向切面编程,这两个是Spring的灵魂. 主要用到的设计模式有工厂模式和代理模式 IOC就是典型的工厂模式,通过ses ...
- 深入理解spring中的AOP原理 —— 实现MethodInterceptor接口,自已动手写一个AOP
1.前言 AOP是面向切面编程,即“Aspect Oriented Programming”的缩写.面对切面,就是面向我们的关注面,不能让非关注面影响到我们的关注面.而现实中非关切面又必不可少,例 ...
- 深入理解Mybatis中sqlSessionFactory机制原理
对于任何框架而言,在使用前都要进行一系列的初始化,MyBatis也不例外.本章将通过以下几点详细介绍MyBatis的初始化过程. 1.MyBatis的初始化做了什么 2. MyBatis基于XML配置 ...
- 图解git,用手绘图带你理解git中分支的原理和应用
大家好,今天我们来聊git当中一个非常非常重要的特性,就是branch. git branch可以说是git当中最重要的概念了,甚至没有之一.因为git最重要的使用场景就是协同开发,大家一起在一个项目 ...
- Python 中生成器的原理
生成器的使用 在 Python 中,如果一个函数定义的内部使用了 yield 关键字,那么在执行函数的时候返回的是一个生成器,而不是常规函数的返回值. 我们先来看一个常规函数的定义,下面的函数 f() ...
- 通过源码理解Spring中@Scheduled的实现原理并且实现调度任务动态装载
前提 最近的新项目和数据同步相关,有定时调度的需求.之前一直有使用过Quartz.XXL-Job.Easy Scheduler等调度框架,后来越发觉得这些框架太重量级了,于是想到了Spring内置的S ...
- IOC容器在web容器中初始化过程——(二)深入理解Listener方式装载IOC容器方式
先来看一下ContextServletListener的代码 public class ContextLoaderListener extends ContextLoader implements S ...
随机推荐
- linux flock()
表头文件 #include<sys/file.h> 定义函数 int flock(int fd,int operation); 函数说明 flock()会依参数operation所指 ...
- 15.队列Queue的特点以及使用,优先级等
#生产者与消费者模式,模式解释:比如MVC设计模式 ''' 1.队列 (1)特点:先进先出 (2)python2 VS python3 python2:from Queue import queue ...
- 利用三层交换机实现VLAN间路由(计算机网络中速率、带宽、吞吐量的概念)
1.速率 速率是指计算机网络中的主机在数字信道上,单位时间内从一端传送到另一端的数据量,即数据传输率,也称数据率或比特率.比特(bit)是数据量的最小单位,s(秒)是时间的最小单位.所以速率单位为bi ...
- postman+xmysql实现postman与数据库的交互,获取数据库的值来作为参数进行请求
安装nodejs和npm详细步骤:https://www.runoob.com/nodejs/nodejs-install-setup.html 安装xmysql 执行命令: npm install ...
- 记录XorDDos木马清理步骤
1.检查 查看定时任务文件发现有两个异常定时任务 [root@manage ~]# cat /etc/crontab # * * * * * user-name command to be execu ...
- redis setNx方法
Redis有一系列的命令,特点是以NX结尾,NX是Not eXists的缩写,如SETNX命令就应该理解为:SET if Not eXists.这系列的命令非常有用,这里讲使用SETNX来实现分布式锁 ...
- Codeforces - 1191F - Tokitsukaze and Strange Rectangle - 组合数学 - 扫描线
https://codeforces.com/contest/1191/problem/F 看了一下题解的思路,感觉除了最后一段以外没什么启发. 首先离散化x加快速度,免得搞多一个log.其实y不需要 ...
- Visual Studio 插件ReSharper:代码生成工具
下载地址:http://www.jetbrains.com/resharper/download/download-thanks.html?code=RSU&platform=windows ...
- typescript 深层次对象内层(N)转外层(N),支持多层级递归转换,多应用于多语言数据结构转换
如下数据结构转换 var a = { b: { en: 1, zh: 2, }, c: { en: 3, zh: 4, }, } //===> var b = { en: { b: 1, c: ...
- 【LeetCode】链表 linked list(共34题)
[2]Add Two Numbers (2018年11月30日,第一次review,ko) 两个链表,代表两个整数的逆序,返回一个链表,代表两个整数相加和的逆序. Example: Input: ( ...