前面在分析了BeanDefinition的资源定位之后,现在主要分析下BeanDefinition的载入,就是说将一个BeanDifinition转化为Spring框架内部的数据结构的过程,今天这篇文章就是分析这个过程的分析
其实就是说这些BeanDefinition在Ioc容器中通过一个HashMap进行相关的操作来完成的
下面还是从DefaultListAbleBeanFoctory来举例说明,从他的设计入手进行解析
第一步:容器的初始化标记,就是在实例化FileSystemXmlApplication的时候调用了refresh()方法,对ioc容器进行了初始化,也就是在这一步是对BeanFoctory这些基本的数据结构进行了一些基本的处理操作
public FileSystemXmlApplicationContext(String[] configLocations, boolean refresh, ApplicationContext parent) throws BeansException {
super(parent);
this.setConfigLocations(configLocations);
//在对FileSystemXmlApplicationContext实例化时调用了Refresh()方法
if (refresh) {
this.refresh();
}
}
//重点就是Refresh()是ioc容器初始化的一个重要的标识
第二部分:解析refresh()中的具体具体实现部分
refresh方法是在AbstractApplicationContext(其实就是FileASystemXmlApplicationContext的基类)中找到,这个方法主要作用就是MessageSource的注册与PostProcessor的注册
如下是具体的代码解析过程:
public void refresh() throws BeansException, IllegalStateException {
synchronized(this.startupShutdownMonitor) {
this.prepareRefresh();
//子类启动RefreshBeanFoctory方法
ConfigurableListableBeanFactory beanFactory = this.obtainFreshBeanFactory();
this.prepareBeanFactory(beanFactory);
try {
//前面讲到的Process注册
this.postProcessBeanFactory(beanFactory);
this.invokeBeanFactoryPostProcessors(beanFactory);
this.registerBeanPostProcessors(beanFactory);
//前面讲到MessageSource
this.initMessageSource();
this.initApplicationEventMulticaster();
this.onRefresh();
//注册(Bean)监听
this.registerListeners();
this.finishBeanFactoryInitialization(beanFactory);
this.finishRefresh();
} catch (BeansException var9) {
this.logger.warn("Exception encountered during context initialization - cancelling refresh attempt", var9);
//销毁掉Bean
this.destroyBeans();
this.cancelRefresh(var9);
throw var9;
} finally {
this.resetCommonCaches();
}
}
第三:就是对第二部分的子类启动的RefreshBeanFoctory的追踪
AbstractRefreshableApplicationContext中的refreshBeanFactory方法的解析`
//其实就是在创建一个容器,如果有beanFactory的话,那么就会对他进行摧毁,并且关闭,然后再新建
protected final void refreshBeanFactory() throws BeansException {
//如果有beanFactory的话,那么就会对他进行摧毁,并且关闭
if (this.hasBeanFactory()) {
this.destroyBeans();
this.closeBeanFactory();
}
try {
// 然后再新建
DefaultListableBeanFactory beanFactory = this.createBeanFactory();
beanFactory.setSerializationId(this.getId());
this.customizeBeanFactory(beanFactory);
this.loadBeanDefinitions(beanFactory);
synchronized(this.beanFactoryMonitor) {
this.beanFactory = beanFactory;
}
} catch (IOException var5) {
throw new ApplicationContextException("I/O error parsing bean definition source for " + this.getDisplayName(), var5);
}
}
第四:主要讲述下其中主要的类继承以及方法的调用流程
第五:调用loadBeanFactory()就是一个抽象方法,实际处理在AbstracrXmlApplicationContext中实现
protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException {
//创建一个XMl中的Reader阅读器
XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);
beanDefinitionReader.setEnvironment(this.getEnvironment());
beanDefinitionReader.setResourceLoader(this);
beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this));
this.initBeanDefinitionReader(beanDefinitionReader);
this.loadBeanDefinitions(beanDefinitionReader);
}
第六:调用LoadBeanFactory的地方,首先获取到BeanDefinition的定位,然后使用XmlBeanDefinitionReader来读取,实际就是用BeanDefinitionReader来读取的
protected void loadBeanDefinitions(XmlBeanDefinitionReader reader) throws BeansException, IOException {
//BeanDefintion的resource资源的获取
Resource[] configResources = this.getConfigResources();
if (configResources != null) {
reader.loadBeanDefinitions(configResources);
}
String[] configLocations = this.getConfigLocations();
if (configLocations != null) {
reader.loadBeanDefinitions(configLocations);
}
}
总结分析:
通过对FileSystemXmlApplicationContext的过程中,通过Ioc容器中的Refresh()方法启动整个BeanDefinition的载入过程的,主要是通过XmlBeanDefintionReader来完成对BeanDefinition的数据结构的读取的,但是实际使用的容器时DefaultListAbleBeanFactory容器,具体的Resource的载入使用XmlBeanDefinitionReader读入BeanDefinition时实现的,以为不同的Spring可以对应不同形式的BeanDefinition,由于这里使用的是XML方式,所以才用的XmlBeanDefinitionReader阅读器来完成数据的加载,其实这个LoadBeanDefinition方法是在其父类就已经做好准备了的