深入spring技术与架构原理
2.2.1 beanFactory对IOC容器的功能与定义
BeanFactory定义了IOC容器的基本功能规范,IOC容器的基本接口是由BeanFactory来定义的。在spring的代码实现中,BeanFactory只是一个接口类,并没有给出容器的具体实现,比如:DefaultListableBeanFactory,XmlBeanFactory,ApplicationContext等都可以看成是容器的附加了某种功能的实现。
BeanFactory接口设计了getBean方法,这个方法是使用IOC容器api的主要方法,通过这个方法可以取得IOC容器中管理的bean,bean的取得是通过名字来进行索引的。
2021-12-21
getBean:
containsBean:是否包含指定名字的Bean
isSingleton:查询指定名称的bean是否是Singleton类型的Bean
isPrototype:查询指定名称的Bean是否是prototype类型的
getType:查询指定名字的Bean的class类型
IOC容器 xmlBeanFactory的工作原理:
继承体系:DefaultListableBeanFactory -》XmlBeanFactory,它提供了IOC容器最基本的功能。从名字可以看出,这个IOC容器可以读取以XML形式定义的BeanDefinition。
理解这一点有助于理解ApplicationContext与基本的BeanFactory之间的区别和联系。我们可以认为直接的BeanFactory实现是IOC容器的基本形式,而各种applicationContext的实现是IOC容器的高级表现形式。XmlBeanFactory是一个可以读取xml文件方式定义的BeanFactory的IOC容器,实现读取xml的功能是怎样实现的?并不是xmlBeanFactory来直接处理的。在xmlBeanFactory中,初始化了一个xmlBeanDefinitionReader对象,实际上就是由这个来完成的。
构造xmlBeanFactory这个ioc容器时,需要指定BeanDefinition的信息来源,而这个信息来源需要封装成spring中的Resource类来给出。比如xml形式的BeanDefinition,那么可以使用ClassPathResource来构造需要的resource,然后做为构造参数传递给xmlBeanFactory。这样,IOC容器就可以方便的定位到BeanDefition信息来对Bean完成容器的初始化和依赖注入。xmlBeanFactory的功能是建立在DefaultBeanFactory这个基本容器的基础上,实现了读取xml的附加功能。对于这些实现原理,从源码中看,在xmlBeanFactory构造方法中得到Resource对象,对xmlBeanDefinitonReader对象初始化,再调用它的loadBeanDefinitons,启动了从Resource载入BeanDefinitons的过程。
2.2.3
applicationContext的特点
相比那些简单拓展BeanFactory的基本IOC容器,开发人员常用的ApplicationContext 除了能提供上面看到的容器基本功能外,还为用户提供了以下的附加服务
1.支持不同的信息源,扩展了MessageSource接口
2.访问资源。体现在对ResourceLoader和Resource的支持上,这样我们可以从不同地方得到Bean定义资源
3.支持应用事件,继承了接口ApplicationEventPublisher,在上下文中引入了事件机制
2.3 IOC容器的初始化
IOC容器的初始化包括BeanDefiniton的resource定位,载入,注册这三个基本的过程。spring在实现中是把这三个过程分开并使用不同模块来完成的。
BeanDefiniton的资源定位由ResourceLoader通过统一的Resource接口来完成的,比如在文件系统中的Bean定义可以用FileSystemResource,在类路径中可以使用ClassPathResource来使用等等。
第二个关键的部分就是BeanDefiniton的载入,载入的过程就是把用户定义好的Bean表示成IOC容器内部的数据结构,这个数据结构就是BeanDefiniton
第三个过程就是向IOC容器注册这些BeanDefiniton的过程。这个过程是调用BeanDefinitonRegistry接口实现来完成的,这个注册过程是把载入过程中解析得到的BeanDefiniton向IOC容器进行注册。在ioc容器内部,是通过一个HashMap来持有这些BeanDefiniton数据的。
2.3.1BeanDefiniton的Resource定位
以编程的方式使用DefaultListableBeanFactory,首先定义一个Resource来定位容器使用的BeanDefiniton,这个Resource并不能让DefaultLisableBeanFactory直接使用,spring是通过BeanDefinitonReader来进行处理的。applicationContext相对于直接使用DefaultListableBeanFactory的好处,因为在applicationContext中,spring已经为我们提供了一系列加载不同Resource的读取器的实现。而这个只是一个纯粹的IOC容器。
例如:FileSysyemXmlApplicationContext,ClassPathXmlApplicationContext等等。可以从名字上看出来它们可以提供哪些不同的Resource读入功能,以FileSystemXmlApplicationContext为例,它继承了abstractApplicationContext具备了ResourceLoader读入以Resource定义的BeanDefinition的能力。在构造函数中通过refresh来启动IOC容器的初始化。重点看refreshBeanFactory的实现,在这个方法里,通过creanteBeanFactory创建了一个IOC容器供applicationContext使用,它启动了loadBeanDefinitons来载入BeanDefiniton。getResourceByPath 返回的是一个 FileSystemResource对象,通过这个对象进行IO操作,完成BeanDefinition的定位。
2021-12-22
2.3.2BeanDefinition的载入和解析
对IOC容器来说,BeanDefinition的载入过程相当于把我们定义的BeanDefiniton在IOC容器中转化成一个spring内部表示的数据结构。IOC容器对Bean的管理和依赖注入功能的实现,是通过对其持有的BeanDefiniton进行各种相关的操作。这些BeanDefiniton数据在IOC容器里通过一个hashMap来保持和维护,通过调用IOC容器 refresh来启动整个BeanDefinition的载入过程。
2.3.3 BeanDefinition在IOC容器的注册
载入和解析后,用户定义的BeanDefinition信息已经在IOC容器内建立了自己的数据结构以及响应的数据表示,但此时这些数据还不能让IOC容器直接使用。需要对这些BeanDefinition数据进行注册。在DefaultListableBeanFactory中,通过一个hashMap来持有载入的BeanDefinition的。实现BeanDefinitionRegistry接口,完成容器的注册,就是把解析得到的BeanDefinition设置到hashMap中去。完成了BeanDefinition的注册,就完成了IOC容器的初始化过程
2021-12-24
2.4 IOC容器的依赖注入
在Bean的创建和对象依赖注入的过程中,需要依据BeanDefinition中的信息来递归地完成依赖注入,这些递归都是以getBean为入口的。一个是在上下文体系中查找需要的Bean和创建Bean的递归调用,另一个递归在依赖注入时,通过递归调用容器的getBean方法,得到当前Bean的依赖Bean,同时也触发了对依赖Bean的创建和注入。根据依赖关系,一层一层地完成Bean的创建和注入,直到最后完成当前Bean的创建。

浙公网安备 33010602011771号