转载自:https://blog.csdn.net/lj1314ailj/article/details/80407753
一、体系结构
IOC 容器的初始化包括 BeanDefinition 的 Resource 定位、载入和注册这三个基本的过程。我们以 ApplicationContext 为例讲解来深入讲解,ApplicationContext系列容器也许是我们最熟悉的,因为 Web项目中使用的XmlWebApplicationContext就属于这个继承体系,还有
ClasspathXmlApplicationContext 等,其继承体系如下图所示:
二、职责分工
IOC容器初始化过程分为定位、载入、注册
定位是根据Resource来完成,
载入是根据BeanDefinitionReader,
剩下就是注册,注册是根据ListableBeanFactory。
下面我们分别简单地演示一下两种 IOC 容器的创建过程,一种是XmlBeanFactory 一种是FileSystemXmlApplicationContext 其中XmlBeanFactory已经被标记为过时的仅仅做简单讲述因为在Spring5.0中XmlBeanFactory已经被标记为过时的,为什么还要说呢!因为XmlBeanFactory相对纯粹也相对简单。
三、XmlBeanFactory IOC容器创建的流程
/**
*DefaultListableBeanFactory 实现了BeanFactory所有子接口
*/
public class XmlBeanFactory extends DefaultListableBeanFactory {
private final XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(this);
public XmlBeanFactory(Resource resource) throws BeansException {
this(resource, null);
}
public XmlBeanFactory(Resource resource, BeanFactory parentBeanFactory) throws BeansException {
super(parentBeanFactory);
this.reader.loadBeanDefinitions(resource);
}
}
该类的依赖关系如下:
定位、载入、注册过程(一切以XmlBeanDefinitionReader 为核心(流程控制),XmlBeanFactory作为门面):
1.定位资源文件的位置(Resource)---------------------------------------------------------------------->定位
2.XmlBeanDefinitionReader读取Resource中的元数据,转为BeanDefinition------------------->加载
3.将第二步的BeanDefinition注册到XmlBeanFactory--------------------------------------------------->注册
四、FileSystemXmlApplicationContext IOC容器创建的流程
ApplicationContext = new FileSystemXmlApplicationContext(xmlPath);
其实际调用的构造函数为:
public FileSystemXmlApplicationContext(
String[] configLocations, boolean refresh, @Nullable ApplicationContext parent)
throws BeansException {
super(parent);
setConfigLocations(configLocations);
if (refresh) {
refresh();
}
}
分析:
1.super(parent) //父类初始化资源加载器
2.setConfigLocations //根据Environment替换路径中的placeHolder字符串
3.refresh()//Bean定义资源的载入是从refresh()函数开始的,refresh()是一个模板方法,refresh()方法的作用是:在创建 IOC 容器前,如果已经有容器存在,则需要把已有的容器销毁和关闭,以保证在 refresh 之后使用的是新建立起来的 IOC 容器。refresh 的作用类似于对 IOC容器的重启。
refresh调用关系如下图:
protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException {
// Create a new XmlBeanDefinitionReader for the given BeanFactory.
XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);
// Configure the bean definition reader with this context's
// resource loading environment.
beanDefinitionReader.setEnvironment(this.getEnvironment());
beanDefinitionReader.setResourceLoader(this);
beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this));
// Allow a subclass to provide custom initialization of the reader,
// then proceed with actually loading the bean definitions.
initBeanDefinitionReader(beanDefinitionReader);
loadBeanDefinitions(beanDefinitionReader);
}
//被上个方法最后一行调用
protected void loadBeanDefinitions(XmlBeanDefinitionReader reader) throws BeansException, IOException {
Resource[] configResources = getConfigResources();
if (configResources != null) {
reader.loadBeanDefinitions(configResources);
}
String[] configLocations = getConfigLocations();
if (configLocations != null) {
reader.loadBeanDefinitions(configLocations);
}
}
问题:
总结(类职责):
(以下分析,从上往下看,父子类关系)
1.FileSystemXmlApplicationContext
主流程调度(1.父容器构建 2.配置文件文件路径处理 3.刷新容器)
2.AbstractXmlApplicationContext
核心流程调度(XmlBeanDefinitionReader 初始化及加载)
3.AbstractRefreshableConfigApplicationContext
增加成员变量(用于配置文件)
路径中特殊符号的处理,多路径分割处理
4.AbstractRefreshableApplicationContext
刷新bean工厂(清空之前的工厂,重新加载工厂)
5.AbstractApplicationContext
bean的初始化的前置、后置处理等核心业务逻辑()