一、前言

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

  虽然对于SpringIoC,我可能连十分之一都还没有弄懂,但是一个下午的研究也不是毫无收获。这篇博客就来简单讲讲我对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

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

  1. 容器解析xml配置文件,将声明在xml文件中的bean的配置信息提取出来,每一个bean的配置信息被封装成一个BeanDefinitionHolder对象。BeanDefinitionHolder主要包含三个成员——BeanDefinition对象,bean的名称(id),以及bean的别名。BeanDefinition对象就是用来保存一个bean的配置信息,比如bean的作用域,bean的类型,bean的依赖,bean的属性......
  2. 容器创建一个ConcurrentHashMap对象,这个mapkeybean的名称,而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在创建完成后,通过beanBeanDefinition对象,获取bean需要注入值的属性,然后为属性赋值,若属性的值类型是其他的bean,则以上面相同的步骤,创建属性对应的bean
  5. 容器创建一个ConcurrentHashMap,将创建好的单例bean保存在其中。我们在代码中可以通过容器的getBean方法,传入bean的名称或类型获取单例bean。容器会先去这个map中查找,若map中不存在,且这个bean的配置在第2步中存储配置信息的map中能够找到,则创建这个bean,放入存储beanmap中(因为bean可以配置延迟加载,即第一次获取时加载);

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

三、总结

  以上内容是我根据自己的认识,对SpringIoC做的一次简单记录,内容并不全面,因为我目前对它的理解也比较浅显。在今天阅读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. Linux 下迁移 Nexus3

    Nexus3 的迁移过程还是非常简单,复制整个目录到新服务器,启动即可. 备份 在原来服务器上将 nexus3 整体目录备份即可. $ tar -zcvf nexus3.tar.gz nexus3/ ...

  2. svg整体缩放至指定大小

    一.问题 svg画面跑在分辨率低的电脑上,导致不能完全显示. 二.要求 svg要能够根据电脑的屏幕大小自动缩放至适配电脑的尺寸. 三.实现 1.获取本机窗口高度.宽度 let clientWidth ...

  3. sqlserver2008 服务器实例连接

    一.sqlserver 配置管理器里面,看sqlserver服务那个,如果只有一个mssqlserver,那就用local或者.来访问,如果不是,可能有命名实例.

  4. 词向量模型word2vector详解

    目录 前言 1.背景知识 1.1.词向量 1.2.one-hot模型 1.3.word2vec模型 1.3.1.单个单词到单个单词的例子 1.3.2.单个单词到单个单词的推导 2.CBOW模型 3.s ...

  5. 基于netty实现rpc框架-spring boot服务端

    demo地址 https://gitee.com/syher/grave-netty RPC介绍 首先了解一下RPC:远程过程调用.简单点说就是本地应用可以调用远程服务器的接口.那么通过什么方式调用远 ...

  6. C++头文件问题

    自己定义的头文件必须要用“***.h”系统头文件必须要用<***.h>stdafx.h 必须放在所有头文件的最前面(如果不放,debug版本没有问题:release版本有问题,会报错)

  7. TeamViewer11 万全免费

    下载地址:百度网盘 c4xm TeamViewer 是一款简单易用且功能强大的远程控制软件,它能穿越内网,摆脱路由器或防火墙的限制,任何一方都不需要拥有固定IP地址.让不懂技术的朋友也能远程控制电脑, ...

  8. 2019-2020-1 20199328《Linux内核原理与分析》第一周作业

    Windows和Linux在收费方面,软件知识方面,安全性.使用习惯.可定制性上以及应用范畴上都有所不同,UNIX/Linux操作系统下的Shell既是用户交互的界面,也是控制系统的脚本语言,其中Ub ...

  9. NPM 私有仓库的搭建

    NPM 私有仓库的搭建 为什么搭建私有仓库 balabala,当然是有需求的时候嘛 搭建流程 介绍和安装verdaccio 备注: 程序启动后,配置文件为/home/work/.config/verd ...

  10. Scala教程之:可扩展的scala

    文章目录 隐式类 限制条件 字符串插值 s 字符串插值器 f 插值器 raw 插值器 自定义插值器 Scala是扩展的,Scala提供了一种独特的语言机制来实现这种功能: 隐式类: 允许给已有的类型添 ...