序言

记得刚毕业那会儿,出来招工作被问到Spring的核心时,都觉得简单的一笔,直接说不就是IoC(控制反转)和DI(依赖注入)么,然后省略一万字对两个名词的解释。最近空来整理了一下Spring中IoC的相关概念,即是复习,也是希望分享出来能帮助到大家更快理解IoC。

其实IoC包括依赖查找(DL)和依赖注入(DI);只不过DL因为有侵入性 (它需要用户自己去是使用 API 进行查找资源和组装对象),已经被抛弃。所以现在提到IoC,更多的想到的就是依赖注入(DI)了。

依赖注入(DI)包括Set注入和构造器注入!其实还有一个通过实现接口的方式实现依赖注入,不过不常用,就不说了。

如图所示:

但其实 IOC 和DI 相当于一回事,只不过是看待问题的角度不同而已:

IOC: Spring 反向控制应用程序需要的资源。

DI: 应用程序依赖Spring为其提供资源。

IOC 是站在Spring 的角度,而DI 是站在应用程序的角度。

如下图所示:

接下来详细介绍一下IoC,从其初始化到实现过程,细细理解!

IoC粗理解

IoC亦称为“依赖倒置原理”(Dependency Inversion Principle),几乎所有框架都使用了倒置注入(Martin Fowler)技巧,是IoC原理的一项应用。SmaIITaIkC++Java.NET面向对象语言的程序员已使用了这些原理。但是Spring是Java语言实现中最著名的一个。同时,控制反转即是Spring框架的核心,也是Spring框架要解决的核心问题。

IoC细理解

由于很多对象的依赖关系和维护并不需要和系统运行状态有很强的关联性,所以可以把在面向对象编程中需要执行的诸如新建对象、为对象引用赋值等操作交由容器统一完成;这样一来,这些散落在不同代码中的功能相同的部分就集中成为容器的一部分,也就是面向对象系统的基础设施的一部分。同时,这些对象之间的相互依赖关系也是比较稳定的,一般不会随着应用的运行状态的改变而改变。

此时,IoC 容器控制了对象,我们直接在对象内部通过new进行创建对象,是程序主动去创建依赖对象这是正转,因为由容器帮我们查找及注入依赖对象,对象只是被动的接受依赖对象,所以是反转;这就解释了控制反转。

基于以上特性,这些对象使用IoC容器来管理,简直就是天作之合。虽然这些特性存在于应用系统中,但是应用系统并不承担管理这些对象的责任,而是通过依赖反转把责任交给了容器(也可以说是平台)。

有了以上这些基础知识储备,Spring IoC容器的原理也就不难理解了。

Spring中IoC的应用

在Spring中,Spring IoC提供了一个基本的JavaBean容器,通过IoC模式管理依赖关系,并通过依赖注入和AOP切面增强了为JavaBea月这样的POJO对象赋予事务管理、生命周期管理等基本功能。

IoC容器

容器的两种表现形式

Spring 作者 Rod Johnson设计了两个接口用以表示容器:BeanFactoryApplicationContext

  • BeanFactory 粗暴简单,可以理解为就是个 HashMap,Key 是 BeanName,Value 是 Bean 实例。通常只提供注册(put),获取(get)这两个功能。我们可以称之为 “低级容器”。

  • ApplicationContext 可以称之为 “高级容器”。因为他比 BeanFactory 多了更多的功能。他继承了多个接口。因此具备了更多的功能。例如资源的获取,支持多种消息(例如 JSP tag 的支持),对 BeanFactory 多了工具级别的支持等待。所以你看他的名字,已经不是 BeanFactory 之类的工厂了,而是 “应用上下文”, 代表着整个大容器的所有功能。该接口定义了一个 refresh 方法,此方法是所有阅读 Spring 源码的人的最熟悉的方法,用于刷新整个容器,即重新加载/刷新所有的 bean。

故我们可以认为直接的BeanFactory实现是IoC容器的基本形式,而各种ApplicationContext的实现是IoC容器的高级表现形式。所以亦可简单的把Spring IoC通过BeanFactory的实现当做低级容器;把ApplicationContext的实现当做高级容器。

此文我们主要讲解Spring 低级容器(BeanFactory)的 IoC;因为高级容器 ApplicationContext,它包含了低级容器的功能,当它执行 refresh 模板方法的时候,将刷新整个容器的 Bean。同时其作为高级容器,它包含了太多的功能,不仅仅是 IoC。它支持不同信息源头,支持 BeanFactory 工具类、支持层级容器、支持访问文件资源、支持事件发布通知、支持接口回调等等。

图片来源于:《Spring技术内幕:深入解析Spring架构与设计原理(第2版)》

BeanFactory的IoC实现过程:

IoC 在 Spring 里,只需要低级容器(BeanFactory)就可以实现,两个步骤:

  • 1、加载配置文件,解析成 BeanDefinition 放在 Map 里。
  • 2、调用 getBean 的时候,从 BeanDefinition 所属的 Map 里,拿出 Class 对象进行实例化,同时,如果有依赖关系,将递归调用 getBean 方法 —— 完成依赖注入。getBean的流程如下所示:

IoC容器初始化过程

值得注意的是,在这个过程中,一般不包含Bean侬赖注入的实现。

在Spring IoC的设计中,Bean定义的载入和依赖注入是两个独立的过程。依赖注入一般发生在应用第一次通过getBean向容器索取Bean的时候。

但有一个例外值得注意,在使用loc容器时有一个预实例化的配置,通过这个预实例化的配置(具体来说,可以通过为Bean定义信息中的lazyinit属性),用户可以对容器初始化过程作一个微小的控制,从而改变这个被设置了]azyinit属性的Bean的依赖注入过程。

举例来说,如果我们对某个Bean设置了lazyinit属性,那么这个Bean的依赖注入在IoC容器初始化时就预先完成了,而不需要等到整个初始化完成以后,第一次使用getBean时才会触发。

BeanDefinition的定位

对loC容器来说,它为管理POJO之间的依赖关系提供了帮助,但也要依据Spring的定义规则提供Bean定义信息。我们可以使用各种形式的Bean定义信息,其中比较熟悉和常用的是使用XML的文件格式。

在Bean定义方面,Spring为用户提供了很大的灵活性。在初始化IoC容器的过程中,首先需要定位到这些有效的Bean定义信息,这里Spring使用Resource接口来统一这些Bean定义信息,而这个定位由ResourceLoader来完成。

  • 如果使用上下文,ApplicationContext本身就为客户提供了定位的功能。因为上下文本身就是DefaultResourceLoader的子类。
  • 如果使用基本的BeanFactory作为loC容器,客户需要做的额外工作就是为BeanFactory指定相应的Resource来完成Bean信息的定位。

BeanDefinition的载入

信息的载入过程。对IoC容器来说,这个载入过程,相当于把定义的BeanDefinition在IoC容器中转化成一个spring内部表示的数据结构的过程。IoC容器对Bean的管理和依赖注入功能的实现,都是通过对其持有的BeanDefinition进行各种相关操作来完成的。这些BeanDefinition数据在IoC容器中通过一个HashMap来保持和维护。当然这只是一种比较简单的维护方式,如果需要提高IoC容器的性能和容量,完全可以自己做一些扩展。

IoC容器的依赖注入

IoC容器的初始化过程完成的主要工作是在IoC容器中建立BeanDefinition数据映射。但在此过程中并没有IoC容器对Bean依赖关系进行注入,那么IoC容器是怎样对Bean的依赖关系进行注入的呢?

假设当前IoC容器已经载入了用户定义的Bean信息,开始分析依赖注入的原理:

首先,依赖注入的过程是用户第一次向容器索要Bean时触发的,当然也有例外,也就是我们可以在BeanDefinition信息中通过控制lazy-init属性来让容器完成对Bean的预实例化。这个预实例化实际上也是一个完成依赖注入的过程,但它是在初始化的过程中完成的。

所以,当用户向IoC容器索要Bean时,如果读者还有印象,那么一定还记得在基本的IoC容器接口BeanFactory中,有一个getBean的接口定义,这个接口的实现就是触发依赖注入发生的地方(也就是依赖注入的入口);而依赖注入的发生是在容器中的BeanDefinition数据已经建立好的前提下才能完成的。

IoC小结

尽管可以用最简单的方式来描述IoC容器,将它视为一个hashMap,但只能说这个hashMap是容器的最基本的数据结构,而不是IoC容器的全部。

打个比方来讲,使用IoC后相当于IoC就是一个饮品店;以前的我们需要自己new对象,也就是需要自己买橙子,买榨汁机来榨果汁喝;而是用IoC后,我们只需要把需求(想喝橙汁)告诉它,然后由它给我们提供橙汁就可以了。这样子想,是不是IoC就感觉简单多了呢?

Spring IoC容器作为一个产品,其价值体现在一系列相关的产品特性上,这些产品特性以依赖反转模式的实现为核心,为用户更好地使用依赖反转提供便利,从而实现了一个完整的IoC容器产品。

参考文章:

  • 1、《Spring技术内幕:深入解析Spring架构与设计原理(第2版)》
  • 2、https://www.cnblogs.com/stateis0/p/9779011.html
  • 3、https://blog.csdn.net/ljk126wy/article/details/87519003

透析Spring(一): Spring之IoC容器理解相关推荐

  1. spring之:XmlWebApplicationContext作为Spring Web应用的IoC容器,实例化和加载Bean的过程...

    它既是 DispatcherServlet 的 (WebApplicationContext)默认策略,又是 ContextLoaderListener 创建 root WebApplicationC ...

  2. Spring(二)IOC容器的初始化流程

    文章目录 一.Spring 核心容器类 1.1 BeanFactory 1.2 ApplicationContext 1.3 BeanDefinition 二.IOC容器的初始化 2.1 基于Xml的 ...

  3. Spring源码分析——IOC容器

    1.IOC容器的概念 理解IOC容器的概念之前首先需要了解依赖翻转(又称依赖倒置)的概念 许多复杂的应用都是通过多个类之间的彼此合作实现业务逻辑的,这使得每个对象都需要管理自己与其合作对象的依赖,而如 ...

  4. Spring核心之对 IOC的理解

    Spring核心之对 IOC的理解 Spring是一个轻量级的控制反转(IOC)和面向切面(AOP)的容器框架. 一 .IOC IOC : Inversion of Control,中文译为" ...

  5. Spring环境搭建,IoC容器初体验~

    由于最近的任务是关于IoC配置文件格式的转换,所以需要从Spring的IoC容器开始学起,今天根据网上的介绍搭建了Spring环境,并对其IoC容器进行了初体验.文章中涉及到的软件以及推荐的一本关于S ...

  6. 请解释下Spring 框架中的IOC 容器?

    Spring 中的org.springframework.beans 包和org.springframework.context 包构成了Spring 框架IOC 容器的基础. BeanFactory ...

  7. Spring源码:IOC容器

    Spring IOC 容器 最底层的IOC容器BeanFactory. 高级形态的IOC容器ApplicationContext. BeanFactory相关类图: ApplicationContex ...

  8. JAVAWEB开发之Spring详解之——Spring的入门以及IOC容器装配Bean(xml和注解的方式)、Spring整合web开发、整合Junit4测试

    Spring框架学习路线 Spring的IOC Spring的AOP,AspectJ Spring的事务管理,三大框架的整合 Spring框架概述 什么是Spring?  Spring是分层的Java ...

  9. Spring是什么?IoC容器的理解

    1. Spring是什么? 我们通常所说的 Spring 指的是 Spring Framework(Spring 框架)⽤⼀句话概括 Spring:Spring 是包含了众多⼯具⽅法的 IoC 容器. ...

最新文章

  1. Python多阶段框架实现虚拟试衣间,超逼真!
  2. 分组背包基础--1712 ACboy needs your help
  3. Hive数据如何同步到MaxCompute之实践讲解
  4. AMR无限增发代币至任意以太坊地址的漏洞利用及修复过程
  5. DTC精彩回顾—王义成:国产数据库技术发展的探索与思考
  6. fatal: protocol error: bad line length character: No s原因
  7. 包含图片,复选框的ListView(转)
  8. ptyhon的列表与字典操作
  9. Spring Data JPA 条件查询 分页查询
  10. javascript 学习总结(五)Function对象
  11. Combo用户板中XG-PON资源利用率的提升方案
  12. Canvas 绘制圆形图片、绘制圆角矩形图片
  13. POJ - 1061 青蛙的约会
  14. Skype应用将在7月1日停止支持Windows Phone 8/8.1等系统
  15. 华为p10关闭更新_华为P10正常升级和强制降级详细方法
  16. ios8在通用设置中文键盘无效的解决方法(中文键盘设置)
  17. 基于RedHatEnterpriseLinux V7(RHEL7)下SPEC CPU 2006环境搭建以及测试流程(之一)——介绍、安装准备、安装、config文件以及运行脚本介绍
  18. PHP中文转拼音及提取首字母
  19. 多方安全计算-秘密共享
  20. 白话空间统计二十一:密度分析(五)带宽与核表面曲率的关系

热门文章

  1. 安卓开发之Bitmap
  2. HCI-人机交互概论 (一)
  3. 基于缎蓝园丁鸟优化算法的无线传感器网络覆盖优化
  4. NLTK读书笔记 — 分类与标注
  5. 基于WSL搭建ESP8266开发环境
  6. iOS开发之模仿qq通讯录
  7. idea psvm 自定义_idea自定义快捷键
  8. Cmake在VS下设置MT
  9. 窥探现代浏览器架构(三)
  10. Word临时文件怎么恢复?可持续的文件恢复方法