一、前言

  这几天正在复习Spring的相关内容,同时想要对Spring的实现原理做一些深入的研究。今天看了看Spring中IoC的实现,找到了一篇非常详细的博客,研究了一个下午,看完之后唯一的感受就是——太复杂了。Spring源码中,类和接口的体系非常的复杂,同时方法的实现也是,方法调用感觉无穷无尽,甚至相互调用,给我绕的晕晕的。应该是自己目前的技术水平还太低,项目经验也不足,甚至对Spring的运用都不够熟悉,所以研究源码对我来说可能还是太早了。

  虽然对于Spring的IoC,我可能连十分之一都还没有弄懂,但是一个下午的研究也不是毫无收获。这篇博客就来简单讲讲我对IoC的理解,以及Spring中,IoC最基本的实现流程。

二、正文

2.1 什么是IoC

  在我们使用传统的编码方式编写代码时,如果在类中需要引用另外一个类的对象,我们一般会直接在类中使用new关键字,创建这样一个对象。此时,使用这个对象的类,就与这个对象所对应的类产生了耦合性。

  IoC中文名称为控制反转,它就是用来解决上述问题的一种设计思想,它能指导我们设计出耦合性更低,更易于管理的代码。传统的程序,都是在需要使用的地方主动地创建对象,而IoC的思想却是将创建对象的工作交给IoC容器去进行。我们告诉IoC容器,它需要创建那些对象,IoC容器创建好这些对象,然后主动地将它们注入到需要使用的地方。此时,需要使用对象的那些类,并不主动地获取对象,而且由IoC容器为它们分配,控制权在IoC容器手上,这就是控制反转。当然,IoC容器并不只是控制对象,可以理解为控制外部资源的获取。

  IoC很好的体现了面向对象设计法则之一—— 好莱坞法则:“别找我们,我们找你”;即由IoC容器帮对象找相应的依赖对象并注入,而不是由对象主动去找。

2.2 IoC和DI的关系

  DI中文名称为依赖注入,它其实和IoC是相同的概念,或者可以理解为它是IoC的一种具体的实现方式。IoC的概念可能比较模糊,控制反转只是一种思想,可能仅仅只是停留在由其他组件控制对象,而不是在使用的地方直接创建这一层面,但是具体如何实现并没有指明。而DI就是它的一种实现思路,由容器创建对象,并主动将对象注入到需要使用它的地方。2.1中对IoC的解释,实际上更加偏向于DI。

2.3 Spring如何实现IoC

  这一块,我就简单地说一说我今天下午在研究Spring的IoC源码的过程中,了解到的一些内容。首先,Spring的IoC容器,可以简单地理解为就是BeanFactory接口的一个实现类对象,比如Spring的应用上下文接口ApplicationContext就是继承自BeanFactory,而我们使用较多的ClassPathXmlApplicationContext就是ApplicationContext的一个实现类。它们都可以理解为是Spring的IoC容器,而BeanFactory就是这个继承体系中的最高层。下面我就以单例bean的创建,简单地说一说Spring的IoC实现的一个过程,假设使用到的是ClassPathXmlApplicationContext这个容器,解析的是xml配置文件:

  1. 容器解析xml配置文件,将声明在xml文件中的bean的配置信息提取出来,每一个bean的配置信息被封装成一个BeanDefinitionHolder对象。BeanDefinitionHolder主要包含三个成员——BeanDefinition对象,bean的名称(id),以及bean的别名。BeanDefinition对象就是用来保存一个bean的配置信息,比如bean的作用域,bean的类型,bean的依赖,bean的属性......
  2. 容器创建一个ConcurrentHashMap对象,这个map的key是bean的名称,而value则是BeanDefinition对象的引用。容器将第一步中解析出的每一个BeanDefinitionHolder对象,它对应的bean名称,以及拥有的BeanDefinition引用放入这个map中。所以,这个map保存了我们在程序中声明的所有的bean的配置信息。
  3. 容器初始化完成后,开始创建bean,遍历第二步中的map集合,获取到bean的名称以及对应的BeanDefinition对象,通过BeanDefinition对象中的信息,判断这个bean有没有定义为延迟加载,若没有,则需要现在就进行创建。在创建前,先通过BeanDefinition中的配置信息,判断此bean有没有depend-on(依赖)其他bean,若有,则先创建当前bean依赖的bean(此处的depend-on不是bean的属性,而是需要通过配置项进行配置的)。之后,则创建当前遍历到的bean。
  4. bean在创建完成后,通过bean的BeanDefinition对象,获取bean需要注入值的属性,然后为属性赋值,若属性的值类型是其他的bean,则以上面相同的步骤,创建属性对应的bean;
  5. 容器创建一个ConcurrentHashMap,将创建好的单例bean保存在其中。我们在代码中可以通过容器的getBean方法,传入bean的名称或类型获取单例bean。容器会先去这个map中查找,若map中不存在,且这个bean的配置在第2步中存储配置信息的map中能够找到,则创建这个bean,放入存储bean的map中(因为bean可以配置延迟加载,即第一次获取时加载);

  Spring中,bean最基本的两种作用域就是singleton(单例)和prototype(多例),默认为单例。以上过程是单例bean的创建过程,若作用域为prototype,则每一次调用getBean方法,都会创建一个新的bean。顺带一提,创建bean的方式是通过反射机制,这个大部分人应该都知道。

三、总结

  以上内容是我根据自己的认识,对Spring的IoC做的一次简单记录,内容并不全面,因为我目前对它的理解也比较浅显。在今天阅读Spring源码的过程中,我发现它真的比我想象中要复杂很多,或许是我水平有限,又或许是没有掌握阅读源码的方法,读起来真的非常吃力。总而言之,想要真正读懂Spring,我还需要很多的学习,希望今后能够尽快提升自己,早日将Spring吃透。

四、参考

简单谈谈Spring的IoC的更多相关文章

  1. 简单理解Spring之IOC和AOP及代码示例

    Spring是一个开源框架,主要实现两件事,IOC(控制反转)和AOP(面向切面编程). IOC 控制反转,也可以称为依赖倒置. 所谓依赖,从程序的角度看,就是比如A要调用B的方法,那么A就依赖于B, ...

  2. 谈谈Spring的IoC之注解扫描

    问题   IoC是Inversion of Control的缩写,翻译过来即"控制反转".IoC可以说是Spring的灵魂,想要读懂Spring,必先读懂IoC.不过有时候硬着头皮 ...

  3. 简单解析Spring核心IOC容器原理

    将大体流程解析了一边,具体可以看源代码一个方法一个方法的跟下 XmlBeanFactory的功能是建立在DefaultListableBeanFactory这个基本容器的基础上的,并在这个基本容器的基 ...

  4. 谈谈Spring中的BeanPostProcessor接口

    一.前言   这几天正在复习Spring的相关内容,在了解bean的生命周期的时候,发现其中涉及到一个特殊的接口--BeanPostProcessor接口.由于网上没有找到比较好的博客,所有最后花了好 ...

  5. JAVA WEB快速入门之通过一个简单的Spring项目了解Spring的核心(AOP、IOC)

    接上篇<JAVA WEB快速入门之从编写一个JSP WEB网站了解JSP WEB网站的基本结构.调试.部署>,通过一个简单的JSP WEB网站了解了JAVA WEB相关的知识,比如:Ser ...

  6. Spring框架-IOC和AOP简单总结

    参考博客: https://blog.csdn.net/qq_22583741/article/details/79589910 1.Spring框架是什么,为什么,怎么用 1.1 Spring框架是 ...

  7. 谈谈Spring Ioc的理解

    原文:http://blog.csdn.net/qq_22654611/article/details/52606960 学了几天Ioc了,但是对它的理解还是模模糊糊,看了这篇博客感觉对Ioc有了更深 ...

  8. spring中IOC的简单使用

    spring的ioc主要就是依赖注入,有基于构造器的依赖注入还有通过设值注入,这里我只简单的实现设值注入的方法,通过spring的依赖管理,我们可以很方便的了解各层之间的依赖关系,降低了各层之间的耦合 ...

  9. (反射+内省机制的运用)简单模拟spring IoC容器的操作

    简单模拟spring IoC容器的操作[管理对象的创建.管理对象的依赖关系,例如属性设置] 实体类Hello package com.shan.hello; public class Hello { ...

随机推荐

  1. Redis linux 下安装

    Redis linux 下安装 下载Redis安装包,可以从Redis中文网站中下载 下载地址:http://www.redis.cn/download.html Redis4.0 稳定版本 使用&l ...

  2. GitHub 热点速览 Vol.16:化身蒙娜丽莎和乔布斯对话

    摘要:妙趣横生,上周的 GitHub 热点的关键词.无论是让你化身为爱因斯坦开启会议脑暴模式 avatarify,还是和上周人人都是抠图师项目的同门项目 3D 照片修复:3d-photo-inpain ...

  3. Shell 变量引用实例

    初学 Shell 编程时,对变量各种引用使用不太熟悉,走了很多弯路,本文记录变量引用的一些用法,希望对大家有所帮助. 引用 引用指将字符串用引用符号引起来,以防止特殊字符被 shell 脚本解释为其他 ...

  4. 简单网络编程如何用python来实现

    对于网络编程,通信模式是后台必备技能,先用最基础代码实现,理解一些 API 的含义,在深入学习. 总是有读者问过我关于 Python 后台开发相关,如果想走 Python 后台方向,对于 Python ...

  5. 常用vscode 插件第一季

    VSCODE 常用插件第一季 1.chinese 此插件中文(简体)语言包为 VS Code 提供本地化界面. https://marketplace.visualstudio.com/items?i ...

  6. SpringMVC数据传递及乱码问题

    基础环境搭建请参考SringMVC入门程序 一.SpringMVC数据处理 1:resful 路径传值 http://localhost/get/1/2 /* http://localhost/get ...

  7. MySQL之外键、主键、自增

    1.创建外键 create table userinfo( uid int auto_increment primary key, name varchar(32), department_id in ...

  8. Python玩转人工智能最火框架 TensorFlow应用实践 学习 教程

    随着 TensorFlow 在研究及产品中的应用日益广泛,很多开发者及研究者都希望能深入学习这一深度学习框架.而在昨天机器之心发起的框架投票中,2144 位参与者中有 1441 位都在使用 Tenso ...

  9. linux下文件的打包和压缩

    文章来源:linux下文件的打包和压缩 目录 一.文件压缩的原理 二.linux常见的压缩指令 三.常用实例 1.tar命令 2.zip命令 3.gz命令 4.bz2命令 5.xz命令(必须分两步) ...

  10. 2019-2020-1 20199326《Linux内核原理与分析》第五周作业

    第五周学习内容 庖丁解牛Linux内核分析第四章:系统调用的三层机制(上) Linux内核分析实验四 学到的一些知识 4.1用户态.内核态.中断 宏观上Linux操作系统的体系架构分为用户态和内核态 ...