(一)Spring IOC容器的设计与实现

控制反转

Spring IoCIoC全称是"Inversion of Control",译:控制反转

"控制反转"又称"依赖反转"

DI全称是"Dependency Injection",译:依赖注入

使用控制反转,依赖注入后,当创建对象时,由一个调度系统将其所依赖的对象的引用传递给它(这些对象也都来自于调度系统所管理的对象),即依赖被注入到对象中。所以,控制反转是关于一个对象如何获取它所依赖的对象的引用

上述的调度系统是应用平台,具体来说是IoC容器。通过使用IoC容器,对象依赖关系的管理被反转了,转到IoC容器中来了,对象之间的相互依赖关系由IoC容器进行管理,并由IoC容器完成对象的注入

IoC容器的核心数据结构

BeanDefinitionIoC容器的核心数据结构。又称"Bean定义信息"。是创建Bean实例时所使用的模板

Bean是容器管理的对象的统称

容器在创建Bean实例之前会先创建BeanDefinition对象,它保存了Bean的定义信息,例如Bean的名字,类型,是单实例还是多实例,是不是懒加载,所依赖的其他对象有哪些等

IoC容器的设计与实现

IoC容器有两个系列

一个是实现BeanFactory接口的简单容器系列,这个系列的容器能实现容器的最基本的功能。又称"Bean工厂"

一个是实现ApplicationContext接口的高级容器系列,它是容器的高级形态。又称"应用上下文"或"上下文"。上下文在简单容器的基础上又增加了许多新功能

Spring IoC容器的设计

下面这张图描述的IoC容器的接口设计图,IoC容器的实现类就是以容器的接口设计为基础实现的

设计主线

  • BeanFactory为核心。从BeanFactoryHierarchicalBeanFactory再到ConfigurableBeanFactory。这是一条主要的BeanFactory类型容器的设计路线
  • ApplicationContext为核心。从BeanFactoryListableBeanFactoryApplicationContext,再到ConfigurableApplicationContextWebApplicationContext。我们常用的上下文基本都是ConfigurableApplicationContextWebApplicationContext的实现类

我们常用的BeanFactory的实现类是DefaultListableBeanFactory。同时,以这个实现类为基础,又有许多应用于不同场景下的子类bean工厂。不过我们通常直接使用DefaultListableBeanFactory

我们常用的ApplicationContext的实现类是AbstractApplicationContext的子类。这个抽象类包含了容器的初始化方法refresh()

AbstractApplicationContext实现的是ConfigurableApplicationContext接口。

BeanFactory的设计原理

这些接口方法定义出了一个基本的IoC容器

  • boolean containsBean(String name);容器中是否有名为nameBean
  • String[] getAliases(String name);查询Bean的所有别名
  • getBean()有多个重载方法,是从容器中获取Bean实例的方法(此方法包含如果获取不到就创建一个Bean实例的流程)
  • boolean isSingleton(String name);返回Bean是否是单实例
  • boolean isPrototype(String name)返回Bean是否是多实例(Bean是单实例还是多实例,这些信息保存在对应的BeanDefinition对象中)
  • ...

这些方法提供了容器最基本的功能

ApplicationContext的设计原理

ApplicationContext除了实现了BeanFactory外还实现了其他接口,为容器添加了其他功能

  • MessageSource信息源。支持国际化功能的实现
  • ResourceLoader访问资源。用于获取 Bean的定义信息所在的资源,为创建 BeanDefinition对象做准备
  • ApplicationEventPublisher发布事件。可以在上下文中,在Bean的生命周期中发布事件
  • ...

容器初始化流程

首先,由编码者使用某种形式编写Bean的配置信息,例如在.xml文件中写标签配置Bean

然后,启动容器进行初始化。容器初始化大致分三步

  1. BeanDefinitionResource定位(定位Bean配置信息所在位置)
  2. 载入BeanDefinition(创建BeanDefinition对象)
  3. 向容器注册BeanDefinition对象(在容器内部将对象put到一个容器持有的map对象中)

在第一次调用容器的getBean()方法(BeanFactory中定义的方法)获取Bean对象时,如果对象还未被实例化,就获取对应的BeanDefinition对象,并使用它作为模板创建实例对象

再容器完成初始化后,调用refresh()方法刷新容器。方法执行完后容器便可以使用

ps:容器初始化的流程可能在refresh()方法外执行,也可能在refresh()方法内执行


本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!

相关文章

立即
投稿

微信公众账号

微信扫一扫加关注

返回
顶部