Board logo

标题: 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]
@Overridepublic 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]
@Overridepublic 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