Spring IOC容器初始化
在Spring IoC容器的设计中,有两个主要的容器系列,一个是实现了BeanFactory接口的简单容器系列,这系列容器只实现了容器的最基本功能;另一个是ApplicationContext 应用上下文,它作为容器的高级形态而存在,除了BeanFactory的基本功能,还提供了更多丰富的功能,常用的实现类有ClassPathXmlApplicationContext、FileSystemXmlApplicationContext、XmlWebApplicationContext。
容器初始化过程本质上就是将BeanDefinition资源进行定位,然后载入容器,再注册到容器的过程
(这个BeanDefinition就是描述这个Bean的定义信息的,因为在Bean标签里我们会设置Bean的id,name,scope作用域,所有的信息都会被封装到BeanDefinition对象中。)
1,定位BeanDefinition资源(通俗讲就是找到定义JavaBean信息的配置文件,并将BeanDefinition资源逐个封装成resource资源对象)
通常手动通过构造器new其中一个实现类创建容器,这时候构造器中会调用一个this.setConfigLocations方法,传入configLocations字符串,这个字符串是资源BeanDefinition所在的文件路径,setConfigLocations方法里的refresh()就是用来触发BeanDefinition资源的定位的。
refresh方法中调用了obtainFreshBeanFactory()方法,这个方法内又调用了refreshBeanFactory()方法,这个方法比较重要,它会创建一个DefaultListableBeanFactory,还
调用loadBeanDefinitions(beanFactory) ,跟进去发现它里面会调用一个同名不同参的重载方法,逐个对BeanDefinition资源进行封装,逐个封装成resource对象,这就完成了资源的定位。
2,载入BeanDefinition(把用户定义好的JavaBean表示为IoC容器内部的数据结构,这个容器内部的数据结构就是BeanDefinition)
XML解析器将resource对象解析成一个document文档,解析之后,然后最终由DefaultBeanDefinitionDocumentReader将document对象解析为BeanDefinitionHolder对象,BeanDefinitionHolder 的作用是根据名称或者别名持有 beanDefinition,承载了 name 和 BeanDefinition 的映射信息。
这个载入过程,本质上就是解析 Resource 对象得到 BeanDefinition的过程,只不过处理的结果是由BeanDefinitionHolder 对象持有。
3,注册BeanDefinition(实际上就是把这些BeanDefinition存入到一个Map集合里)
封装之后,它会调用 registerBeanDefinition 方法解析 BeanDefinitionHolder 对象,按照 Bean 的名称、别名将 BeanDefinition 注册到 IoC 容器中,所谓的注册到容器,实际上就是把这些BeanDefinition存入到一个Map集合里。
SpringIOC里有一个核心的Bean工厂对象,叫做DefaultListableBeanFactory,它里面本质上是维护了一个叫BeanDefinitionMap的集合,专门用来存储Bean的定义的,底层是ConcurrentHashMap,我们刚刚所封装的BeanDefinition就以Bean的ID作为Key,BeanDefinition对象作为Value,存到这个Map集合,当每一个BeanDefinition对象都以这种方式存入到这个集合,我们就说这个注册这个操作都完成了。
另外:
操作完成之后如果是非抽象 、 并且不是懒加载的单例对象会被立刻创建。因为单例对象只需要创建一次,所以就可以在这时候构建容器的时候,都给他提前创建好。
创建出来的单例对象会存储到一个叫singletonObjects 的map集合中,这个集合也是DefaultListableBeanFactory所维护的,也是一个ConcurrentHashMap集合。