标题:
Spring IoC容器的初始化过程(2)
[打印本页]
作者:
look_w
时间:
2018-12-15 13:50
标题:
Spring IoC容器的初始化过程(2)
在loadBeanDefinitions中创建了XmlBeanDefinitionReader实例,然后在IoC容器中设置该实例,最后通过loadBeanDefinitions方法来完成Bean定义在IoC容器中的载入。接下来看下真正实现加载BeanDefinitions的loadBeanDefinitions(beanDefinitionReader)方法:
[url=]
[/url]
protected
void
loadBeanDefinitions(XmlBeanDefinitionReader reader)
throws
BeansException, IOException { Resource[] configResources
= getConfigResources();
//
获得Bean配置文件的资源位置
if
(configResources !=
null
) {
//
读取AbstractBeanDefinitionReader中定位的资源
reader.loadBeanDefinitions(configResources); }
//
获取ClassPathXmlApplicationContext构造方法中setConfigLocations方法设置的资源
String[] configLocations =
getConfigLocations();
if
(configLocations !=
null
) {
//
读取AbstractBeanDefinitionReader中定位的资源,最终还是以Resource的形式去加载资源。
reader.loadBeanDefinitions(configLocations); }}
[url=]
[/url]
在AbstractBeanDefinitionReader的loadBeanDefinitions中开始进行BeanDefinitions的载入。
[url=]
[/url]
@Override
public
int
loadBeanDefinitions(Resource... resources)
throws
BeanDefinitionStoreException { Assert.notNull(resources,
"Resource array must not be null"
);
int
counter = 0
;
for
(Resource resource : resources) { counter
+=
loadBeanDefinitions(resource); }
return
counter;}
[url=]
[/url]
以上代码中的loadBeanDefinitions在AbstractBeanDefinitionReader中并没有实现,它只是一个在BeanDefinitionReader中定义的接口方法,具体的实现在各个子类(如:XmlBeanDefinitionReader)中。
在XmlBeanDefinitionReader中实现的loadBeanDefinitions方法会得到一个XML文件的InputStream,然后会获得一个InputResource,调用doLoadBeanDefinitions(inputSource, encodedResource.getResource())返回。doLoadBeanDefinitions方法是去从XML文件中加载BeanDefinitions,具体的过程是在该方法调用了registerBeanDefinitions(doc, resource)。
[url=]
[/url]
public
int
registerBeanDefinitions(Document doc, Resource resource)
throws
BeanDefinitionStoreException {
//
这里得到BeanDefinitionDocumentReader来对XML的BeanDefinition进行解析
BeanDefinitionDocumentReader documentReader =
createBeanDefinitionDocumentReader();
int
countBefore =
getRegistry().getBeanDefinitionCount();
//
具体的解析过程在registerBeanDefinitions中完成
documentReader.registerBeanDefinitions(doc, createReaderContext(resource));
return
getRegistry().getBeanDefinitionCount() -
countBefore;}
[url=]
[/url]
通过上面的代码可以知道具体的解析XML并转换为容器内部结构的过程是在BeanDefinitionDocumentReader中完成的,registerBeanDefinitions还对载入的Bean数量进行了统计。这里使用的documentReader是通过createBeanDefinitionDocumentReader()方法创建的默认的DefaultBeanDefinitionDocumentReader。而DefaultBeanDefinitionDocumentReader中定义了Spring的Bean规则。
[url=]
[/url]
@Override
public
void
registerBeanDefinitions(Document doc, XmlReaderContext readerContext) {
this
.readerContext =
readerContext; logger.debug(
"Loading bean definitions"
); Element root
=
doc.getDocumentElement(); doRegisterBeanDefinitions(root);}
[url=]
[/url]
在doRegisterBeanDefinitions中,由BeanDefinitionParserDelegate实现了解析过程。
View Code
通过一路跟进parseBeanDefinitions方法,可以找到以下代码:
View Code
在processBeanDefinition方法中处理BeanDefinitions,具体的处理工作交给了BeanDefinitionParserDelegate的parseBeanDefinitionElement,并且得到结果BeanDefinitionHolder,然后向IoC容器注册解析到的BeanDefinition,注册完成之后发送消息。BeanDefinitionParserDelegate类包含了对各种Spring Bean定义规则的处理。BeanDefinitionHolder是BeanDefinition的封装类,封装了BeanDefinition,Bean的名字、别名。用它来完成想IoC容器注册。
View Code
以下代码是对Bean元素的详细解析:
View Code
以上就是BeanDefinition在IoC容器中的载入和解析过程。
在上面的DefaultBeanDefinitionDocumentReader类的processBeanDefinition方法中我们看到有这么一行代码:BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry());。这里的作用是想IoC容器注册解析后获得到的BeanDefinition。通过追踪代码,发现DefaultListableBeanFactory实现了在BeanDefinitionRegistry中定义的registerBeanDefinition方法。
View Code
总结:
[url=]
[/url]
IoC容器初始化的入口是在构造方法中调用refresh()开始的。通过ResourceLoader来完成资源文件位置的定位,DefaultResourceLoader是默认的实现,同时上下文本身就给出了ResourceLoader的实现。创建的IoC容器是DefaultListableBeanFactory。IoC容器对Bean的管理和依赖注入功能的实现是通过对其持有的BeanDefinition进行相关操作来完成的。通过BeanDefinitionReader来完成定义信息的解析和Bean信息的注册。XmlBeanDefinitionReader是BeanDefinitionReader的实现类,通过它来解析XML配置中的bean定义。实际的处理过程是委托给 BeanDefinitionParserDelegate来完成的。得到bean的定义信息,这些信息在Spring中使用BeanDefinition对象来表示。BeanDefinition的注册是由BeanDefinitionRegistry实现的registerBeanDefinition方法进行的。内部使用ConcurrentHashMap来保存BeanDefinition。
欢迎光临 电子技术论坛_中国专业的电子工程师学习交流社区-中电网技术论坛 (http://bbs.eccn.com/)
Powered by Discuz! 7.0.0