【Spring IOC容器学习笔记】一——什么是Spring IOC容器,它是怎么工作的

谁践踏了优雅 2021-12-11 23:55 454阅读 0赞

摘要

Spring IOC容器是Spring的核心功能,它构成了Spring框架的骨骼结构,没有它就没有上层MVC、AOP等高级特性。这节的学习笔记主要回答下面几个问题:

  • Spring IOC容器是用来做什么的?
  • 什么是bean?
  • Spring IOC容器是如何工作的?
  • Spring IOC容器与BeanFactory和ApplicationContext的关系是什么?

1 Spring IOC容器与bean

1.1 什么是Spring IOC 容器

在这里插入图片描述
把Spring IOC 容器看做一个黑盒,它的功能就是根据读取的配置元数据,将应用中的业务对象(POJOs)实例化后建立互相之间的依赖关系,提供给我们一个可使用的系统。

1.2 什么是bean

每个业务对象,经过容器的实例化得到的就是bean。bean被容器管理相互间的依赖关系,组成应用。在我的另一篇学习笔记里有bean的详细介绍,这里就不展开了。

1.3 怎么理解IOC

IOC是Inverse of Controll的简写,翻译为控制反转,指的是被实例化的对象对依赖创建的控制权从自身转移到容器。IOC的概念比较晦涩,我们可以借助依赖注入(Dependency Injection,DI)的概念辅助理解它。依赖注入的过程是指,POJO被容器实例化后,由容器负责将它的依赖准备好供使用。关于依赖的更详细说明可以看另外一篇学习笔记。

IOC技术与直接通过new 方法创建依赖相比有什么优点?

  • 代码更加简洁
  • 实现了依赖的创建和使用的解耦(使用依赖的类不用再关心去哪里找依赖去创建)
  • 更容易进行单元测试

2 Spring IOC容器工作原理

这部分,我们进入Spring IOC 内部,看它由哪些组件构成,是怎么工作的。
容器中的每一个bean都会有一个对应的BeanDefinition实例,该实例负责保存bean对象的所有必要信息,包括bean对象的class类型、是否是抽象类、构造方法和参数、其它属性等等。当客户端向容器请求相应对象时,容器就会通过这些信息准备一个完整可用的bean实例返回给客户端。
BeanDefinitionRegistry抽象了bean的注册逻辑,包含registerBeanDefinition()、removeBeanDefinition()、getBeanDefinition()等注册管理BeanDefinition的方法。
BeanFactory抽象了bean的管理逻辑,包含getBean、containBean、getType、getAliases等管理bean的方法。
他们的关系如下图:
在这里插入图片描述
Spring IOC 容器的工作流程大致分为两个阶段:

阶段1:容器启动

容器在这阶段的主要工作是收集bean信息,也会进行一些验证性和辅助性的工作。容器要加载Configuration Meta信息,除了纯java代码实现配置的情况,其他方式如通过XML文件的读取,需要借助BeanDefinitionReader组件进行解析。BeanDefinitionReader读取和分析Configuration Meta信息后,组装信息为bean对应的BeanDefinition,并把它注册到BeanDefinitonRegistry中,就完成了容器启动。示例代码:

  1. // 通常为BeanDefinitionRegistry的实现类,这里以DeFaultListabeBeanFactory为例
  2. BeanDefinitionRegistry beanRegistry = new DefaultListableBeanFactory();
  3. // XmlBeanDefinitionReader实现了BeanDefinitionReader接口,用于解析XML文件
  4. XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReaderImpl(beanRegistry);
  5. // 加载配置文件
  6. beanDefinitionReader.loadBeanDefinitions("classpath:spring-bean.xml");

阶段2:实例加载

经过阶段1后,当某个请求通过容器的getBean方法请求某个对象,或者因为依赖关系容器需要隐式的调用getBean时,就会触发阶段2的工作:容器会首先检查所请求的对象之前是否已经实例化完成。如果没有,则会根据注册的BeanDefinition所提供的信息实例化被请求对象,并为其注入依赖。当该对象装配完毕后,容器会立即将其返回给请求方法使用。

  1. // 从容器中获取bean实例
  2. BeanFactory container = (BeanFactory)beanRegistry;
  3. Business business = (Business)container.getBean("beanName");

3 BeanFactory和ApplicationContext

BeanFactory可以管理任何对象,它是Spring IOC容器一种简单的实现,提供了最基本的依赖注入(DI)支持。而在实际场景下,我们更多的使用另外一种类型的容器:ApplicationContext,它集成自BeanFactory,除了基本DI功能,还提供了更高级的功能,如事件监听。
两者bean实例加载策略有区别:BeanFactory默认是延迟加载策略,即只有当访问容器中的某个对象时,才对该对象进行实例化和依赖注入操作;ApplicationContext则模式在容器启动时就全部完成实例化和依赖注入操作。

总结

对使用者来说,可以把spring 容器看做一个生产工厂,它提前根据生产说明(Configuration Meta)把物料(POJOs)加工成产品(beans),使用者只要报出需要的产品名字(beanName)就可以得到提前生产好的产品,整体是简单工厂模式的体现。
容器的实现可以是简单的BeanFactory或更高级的ApplicationContext。它们借助BeanDefiniton组件实现对bean及依赖信息的管理, 容器启动时收集所有bean的信息。当实例化bean的时候,容器负责将其依赖对象也进行实例化以供使用,这个过程就是依赖注入。

参考资料

1,给你一份Spring Boot知识清单
2,Spring Core Technologies

发表评论

表情:
评论列表 (有 0 条评论,454人围观)

还没有评论,来说两句吧...

相关阅读

    相关 什么IOC容器

    .IOC不是一种技术,只是一种思想,一个重要的面向对象编程的法则,它能指导我们如何设计出松耦合,更优良的程序。传统应用程序都是由我们在类内部主动创建依赖对象,从而导致类与...

    相关 什么 Spring IOC 容器

    Spring 框架的核心是 Spring 容器。容器创建对象,将它们装配在一起,配置它们并管理它们的完整生命周期。Spring 容器使用依赖注入来管理组成应用程序的组件。容器通