IOC容器初始化过程中4个比较重要的类
1.BeanFactory系列:只实现IOC容器的基本功能
BeanFactory的基本功能:
a.通过containBean方法判断IOC容器中是否含有指定名字的Bean
b.通过isSingleton方法查询指定名字的Bean是否为Singleton类型的Bean
c.通过isPrototype方法查询指定名字的Bean是否为Prototype类型的Bean
d.通过isTypeMatch方法查询指定了名字的Bean的Class类型是否是特定的Class类型
e.通过getType方法查询指定名字的Bean的Class类型
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提供的如URL、File等不足以支持spring获取各种不同来源的资源的操作(如缺少从类路径或web容器上下文获取资源),因此spring框架提供了一个更为可靠的接口Resource用来抽象规范各种不同来源的资源,主要实现类如下:
4.BeanDefinition:管理基于spring的应用中的各种对象以及它们之间的依赖关系,是对依赖反转模式中管理的对象依赖关系的数据抽象,是容器实现依赖反转功能的核心数据结构
FactoryBean与BeanFactory的区别
FactoryBean:产生对象的工厂,不是一个简单的Bean,是能产生or修饰对象生成的工厂Bean
BeanFactory:IOC容器,所有Bean都是由其管理的
使用容器时,可使用“&”来得到FactoryBean本身,用于区分通过容器获取的是FactoryBean产生的对象还是FactoryBean对象本身
IOC容器的接口设计,如下图
图摘自《spring技术内幕:深入解析spring架构与设计原理》
IOC容器的初始化过程
主要包括BeanDefinition的Resource定位、载入和注册这3个过程
Resource定位:指BeanDefinition的资源定位,由ResourceLoader通过统一的Resource接口来完成
BeanDefinition的载入:将用户定义好的Bean表示成IOC容器内部的数据结构
BeanDefinition的注册:通过BeanDefinitionRegistry接口的实现来完成,将上一步骤解析得到的BeanDefinition向IOC容器进行注册
1. BeanDefinition的Resource定位:
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的文件对象,得到文件对象后就可以按照spring对Bean的定义规则来对该xml文档进行解析,具体解析在BeanDefinitionParserDelegate中完成(有兴趣可以看,反正我是不看额)
到XmlBeanDefinitionReader中看下loadBeanDefinitions(Resource resource)方法具体是如何实现BeanDefinition载入的:
而spring的BeanDefinition如何按照spring的Bean语义要求进行解析并转化为容器内部数据结构的,这个过程是在BeanDefinitionDocumentReader类中完成的,具体如下:
BeanDefinitionHolder封装很简单,如下:
到此,Resource的载入就完成了,主要分为2部分,先是通过DefaultDocumentLoader解析xml文件得到Document对象,这些Document对象只是通用的xml解析对象,并不是按照spring的Bean规则进行解析的;完成通用的xml解析后,使用BeanDefinitionDocumentReader按照spring的Bean规则进行解析,具体解析是在BeanDefinitionParserDelegate中完成的,解析结果由BeanDefinitionHolder对象持有,最后使用BeanDefinitionHolder向IOC容器注册BeanDefinition信息
3. Resource的注册:
Resource注册的入口在DefaultBeanDefinitionDocumentReader中,如下:
到BeanDefinitionReaderUtils中:
其中的BeanDefinitionRegistry其实就是DefaultListableBeanFactory,因为其实现了BeanDefinitionRegistry接口
在DefaultListableBeanFactory中其实就是使用一个ConcurrentHashMap来持有载入的BeanDefinition对象的,BeanDefinition的注册的具体实现在DefaultListableBeanFactory中,如下:
别名的注册是在SimpleAliasRegistry类中实现的,具体如下:
到此,IOC容器的BeanDefinition的注册就已经完成了,整个IOC容器的初始化过程也完毕,DefaultListableBeanFactory中已经建立了整个Bean的配置信息,IOC容器的责任就是对这些信息进行维护和处理,这些信息是IOC容器建立依赖反转的基础