IoC容器的设计与实现
BeanFactory 和 ApplicationContext
在Spring IoC容器的设计中,可以看到两个主要的容器系列,一个是实现BeanFactory 接口的简单容器系列,这系列容器只实现了容器的最基本功能;另一个是ApplicationContext 应用上下文,它作为容器的高级形态而存在。 应用上下文在简单容器的基础上,增加了许多面向框架的特性,同时对应用环境作了许多适配。
IoC容器
其实对IoC容器的使用者来说,我们经常接触到的BeanFactory和ApplicationContext都可以看成是容器的具体表现形式。我们通常说的IoC容器,实际上代表着一系列功能各异的容器产品,只是容器的功能有各自的特点。
Spring通过定义BeanDefinition来管理基于Spring的应用中的各种对象以及他们之间的相互依赖关系。IoC容器是用来管理对象依赖关系的,对IoC容器来说,BeanDefinition就是对依赖反转模式中管理的对象依赖关系的数据抽象,也是容器实现依赖反转功能的核心数据结构,依赖反转功能都是围绕对这个BeanDefinition的处理来完成的。
IoC容器的初始化过程
简单来说,IoC容器的初始化是由refresh()方法来启动的,这个方法标志容器的正式启动。这个启动包括BeanDefinition的Resource定位、载入和注册三个基本过程。
Resource定位过程
这个定位指的是BeanDefinition的资源定位,它由ResourceLoader通过统一的esource接口来完成,这个Resource对各种形式的BeanDefinition的使用都提供了统一接口。对于这些BeanDefinition的存在形式,例如:在类路径中ClassPathResource。定位的过程类似于容器寻找数据的过程,就像用水桶装水先要把水找到一样。
BeanDefinition的载入
这个载入的过程是把用户定义好的Bean表示成IoC容器内部的数据结构,而这个容器内部的数据结构就是BeanDefinition。具体来说,这个BeanDefinition实际上就是POJO对象在IoC容器中的抽象,通过这个BeanDefinition定义的数据结构,使IoC容器能够方便管理Bean对象。
IoC容器注册
这一步是将载入过程中解析BeanDefinition得到的Bean向IoC容器注册的过程。通过调BeanDefinitionRegistry接口的实现来完成。IoC容器通过HashMap来存储这些解析得到的Bean。
这个过程不包含Bean依赖注入的实现。依赖注入一般发生在应用第一次通过getBean向容器获取Bean的时候。但有个例外,IoC容器有一个预实例化的配置(Bean的lazyinit属性),如果定义的Bean有这个属性,那么这个Bean的依赖注入在IoC容器初始化时就完成了,不需要等到整个初始化完成以后,第一次使用getBean获取时才触发。
BeanDefinition的Resource定位
在ApplicationContext中,Spring已经为我们提供了一系列加载不同Resource的读取器的实现,例如常用的FileSystemXmlApplicationContext、ClassPathXmlApplicationContext以及XmlWebApplicationContext等。
待续