Spring框架学习[IoC容器解析Bean](一)

2014-11-24 03:05:58 · 作者: · 浏览: 0

1.通过前两篇博客的分析,我们已经了解了Spring IoC容器定位和载入Bean定义资源文件的基本过程,接下来我们要继续分析Spring IoC容器将载入的Bean定义资源文件转换为Document对象之后,是如何将其解析为Spring IoC管理的Bean对象并将其注册到容器中的。

2.XmlBeanDefinitionReader解析载入的Bean定义资源文件:

XmlBeanDefinitionReader类中的doLoadBeanDefinitions方法是从特定XML文件中实际载入Bean定义资源的方法,该方法在载入Bean定义资源之后将其转换为Document对象,接下来调用registerBeanDefinitions启动Spring IoC容器对Bean定义的解析过程,registerBeanDefinitions方法源码如下:

[java]
  1. //按照Spring的Bean语义要求将Bean定义资源解析并转换为容器内部数据结构 public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException {
  2. //得到BeanDefinitionDocumentReader来对xml格式的BeanDefinition解析 BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader();
  3. //获得容器中注册的Bean数量 int countBefore = getRegistry().getBeanDefinitionCount();
  4. //解析过程入口,这里使用了委派模式,BeanDefinitionDocumentReader只是个接口,//具体的解析实现过程有实现类DefaultBeanDefinitionDocumentReader完成 documentReader.registerBeanDefinitions(doc, createReaderContext(resource));
  5. //统计解析的Bean数量 return getRegistry().getBeanDefinitionCount() - countBefore;
  6. } //创建BeanDefinitionDocumentReader对象,解析Document对象
  7. protected BeanDefinitionDocumentReader createBeanDefinitionDocumentReader() { return BeanDefinitionDocumentReader.class.cast(BeanUtils.instantiateClass(this.documentReaderClass));
  8. }

    Bean定义资源的载入解析分为以下两个过程:

    首先,通过调用XML解析器将Bean定义资源文件转换得到Document对象,但是这些Document对象并没有按照Spring的Bean规则进行解析。这一步是载入的过程

    其次,在完成通用的XML解析之后,按照Spring的Bean规则对Document对象进行解析。

    按照Spring的Bean规则对Document对象解析的过程是在接口BeanDefinitionDocumentReader的实现类DefaultBeanDefinitionDocumentReader中实现的。

    3.DefaultBeanDefinitionDocumentReader对Bean定义的Document对象解析:

    BeanDefinitionDocumentReader接口通过registerBeanDefinitions方法调用其实现类DefaultBeanDefinitionDocumentReader对Document对象进行解析,解析的代码如下:

    [java]
    1. //根据Spring DTD对Bean的定义规则解析Bean定义Document对象 public void registerBeanDefinitions(Document doc, XmlReaderContext readerContext) {
    2. //获得XML描述符 this.readerContext = readerContext;
    3. logger.debug(Loading bean definitions); //获得Document的根元素
    4. Element root = doc.getDocumentElement(); //具体的解析过程由BeanDefinitionParserDelegate实现,
    5. //BeanDefinitionParserDelegate中定义了Spring Bean定义XML文件的各种元素 BeanDefinitionParserDelegate delegate = createHelper(readerContext, root);
    6. //在解析Bean定义之前,进行自定义的解析,增强解析过程的可扩展性 preProcessXml(root);
    7. //从Document的根元素开始进行Bean定义的Document对象 parseBeanDefinitions(root, delegate);
    8. //在解析Bean定义之后,进行自定义的解析,增加解析过程的可扩展性 postProcessXml(root);
    9. } //创建BeanDefinitionParserDelegate,用于完成真正的解析过程
    10. protected BeanDefinitionParserDelegate createHelper(XmlReaderContext readerContext, Element root) { BeanDefinitionParserDelegate delegate = new BeanDefinitionParserDelegate(readerContext);
    11. //BeanDefinitionParserDelegate初始化Document根元素 delegate.initDefaults(root);
    12. return delegate; }
    13. //使用Spring的Bean规则从Document的根元素开始进行Bean定义的Document对象 protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) {
    14. //Bean定义的Document对象使用了Spring默认的XML命名空间 if (delegate.isDefaultNamespace(root)) {
    15. //获取Bean定义的Document对象根元素的所有子节点 NodeList nl = root.getChildNodes();
    16. for (int i = 0; i < nl.getLength(); i++) { Node node = nl.item(i);
    17. //获得Document节点是XML元素节点 if (node instanceof Element) {
    18. Element ele = (Element) node; //Bean定义的Document的元素节点使用的是Spring默认的XML命名空间
    19. if (delegate.