源码角度,理清spring IOC容器初始化的全过程

IOC容器初始化过程中4个比较重要的类

1.BeanFactory系列:只实现IOC容器的基本功能

BeanFactory的基本功能:

a.通过containBean方法判断IOC容器中是否含有指定名字的Bean

b.通过isSingleton方法查询指定名字的Bean是否为Singleton类型的Bean

c.通过isPrototype方法查询指定名字的Bean是否为Prototype类型的Bean

d.通过isTypeMatch方法查询指定了名字的BeanClass类型是否是特定的Class类型

e.通过getType方法查询指定名字的BeanClass类型

f.通过getAliases方法查询指定名字的Bean的所有别名

g.通过getBean方法获取指定name或指定Class类型的Bean对象


2.ApplicationContext系列:高级容器,在简单容器的基础上增加了许多对应用框架、环境的适配,是IOC容器的高级表现形式

ApplicationContext的新特性:

a.支持不同的信息源:扩展了MessageSource接口,可支持国际化实现,为多语言版本应用提供服务

b.访问资源:继承了ResourceLoader接口,可从不同的I/O途径得到Bean定义资源

c.支持应用事件:继承了ApplicationEvenPublisher接口,在上下文中引入事件机制,这些事件和Bean的生命周期结合为Bean的管理提供了便利

3.Resource系列:由于jdk提供的如URLFile等不足以支持spring获取各种不同来源的资源的操作(如缺少从类路径或web容器上下文获取资源),因此spring框架提供了一个更为可靠的接口Resource用来抽象规范各种不同来源的资源,主要实现类如下:


4.BeanDefinition:管理基于spring的应用中的各种对象以及它们之间的依赖关系,是对依赖反转模式中管理的对象依赖关系的数据抽象,是容器实现依赖反转功能的核心数据结构

FactoryBean与BeanFactory的区别

FactoryBean:产生对象的工厂,不是一个简单的Bean,是能产生or修饰对象生成的工厂Bean

BeanFactoryIOC容器,所有Bean都是由其管理的

使用容器时,可使用&”来得到FactoryBean本身,用于区分通过容器获取的是FactoryBean产生的对象还是FactoryBean对象本身

IOC容器的接口设计,如下图


图摘自《spring技术内幕:深入解析spring架构与设计原理》

IOC容器的初始化过程

主要包括BeanDefinitionResource定位、载入和注册这3个过程

Resource定位:指BeanDefinition的资源定位,由ResourceLoader通过统一的Resource接口来完成

BeanDefinition的载入:将用户定义好的Bean表示成IOC容器内部的数据结构

BeanDefinition的注册:通过BeanDefinitionRegistry接口的实现来完成,将上一步骤解析得到的BeanDefinitionIOC容器进行注册

1. BeanDefinitionResource定位:


refresh方法的具体实现在父类AbstractApplicationContext中,具体如下:

refreshBeanFactory具体实现在子类AbstractRefreshableApplicationContext中,具体如下:

loadBeanDefinition的具体实现在子类AbstractXmlApplicationContext中,具体如下:

XmlBeanDefinitionReader类中读取BeanDefinition信息,具体如下:

DefaultResourceLoader类中完成对Resource的定位,具体如下:

crtl+T看下getResourceByPath方法的实现关系,会发现FileSystemXmlApplicationContext实现了该方法,于是Resource的定位走了一圈回到了FileSystemXmlApplicationContext类中,生成并返回了一个FileSystemResource


通过FileSystemResource对象,spring便可以进行相关的I/O操作,完成BeanDefinition定位,该过程实现的就是对path进行解析后生成一个FileSystemResource对象返回的过程,至此,BeanDefinition定位的过程便完成了

2.Resource的载入:

载入过程是在XmlBeanDefinitionReader中实现的(FileSystemXmlApplicationContext使用的是xml方式的定义,若是其他不同的定义,则采用其他BeanDefinitionReader),载入之前XmlBeanDefinitionReader的父类AbstractXmlBeanDefinition已为BeanDefinition的载入做好准备,实现在AbstractXmlBeanDefinition中,具体如下:

上面的loadBeanDefinitions(Resource resource)方法具体实现在子类XmlBeanDefinitionReader中,在读取器中,需得到代表xml文件的Resource对象,因Resource对象封装了对xml文件的I/O操作,读取器便可以在打开I/O流后得到xml的文件对象,得到文件对象后就可以按照springBean的定义规则来对该xml文档进行解析,具体解析在BeanDefinitionParserDelegate中完成(有兴趣可以看,反正我是不看额)

XmlBeanDefinitionReader中看下loadBeanDefinitions(Resource resource)方法具体是如何实现BeanDefinition载入的:

springBeanDefinition如何按照springBean语义要求进行解析并转化为容器内部数据结构的,这个过程是在BeanDefinitionDocumentReader类中完成的,具体如下:

BeanDefinitionHolder封装很简单,如下:

到此,Resource的载入就完成了,主要分为2部分,先是通过DefaultDocumentLoader解析xml文件得到Document对象,这些Document对象只是通用的xml解析对象,并不是按照springBean规则进行解析的;完成通用的xml解析后,使用BeanDefinitionDocumentReader按照springBean规则进行解析,具体解析是在BeanDefinitionParserDelegate中完成的,解析结果由BeanDefinitionHolder对象持有,最后使用BeanDefinitionHolderIOC容器注册BeanDefinition信息

3. Resource的注册:

Resource注册的入口在DefaultBeanDefinitionDocumentReader中,如下:

BeanDefinitionReaderUtils中:

其中的BeanDefinitionRegistry其实就是DefaultListableBeanFactory,因为其实现了BeanDefinitionRegistry接口

DefaultListableBeanFactory中其实就是使用一个ConcurrentHashMap来持有载入的BeanDefinition对象的,BeanDefinition的注册的具体实现在DefaultListableBeanFactory中,如下:

别名的注册是在SimpleAliasRegistry类中实现的,具体如下:

到此,IOC容器的BeanDefinition的注册就已经完成了,整个IOC容器的初始化过程也完毕,DefaultListableBeanFactory中已经建立了整个Bean的配置信息,IOC容器的责任就是对这些信息进行维护和处理,这些信息是IOC容器建立依赖反转的基础



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章