spring源码(三)--XmlBeanDefinitionReader(转载)

原文出处:https://blog.csdn.net/ljz2016/article/details/82768944

 

类继承层次图:

  BeanDefinitionReader                          定义资源文件读取并转换为BeanDefinition的功能
  EnvironmentCapable                           定义了获取Environment的方法
  AbstractBeanDefinitionReader            对上面2个接口做了实现
  XmlBeanDefinitionReader                   读取配置文件的大致流程

 

  通过继承自 AbstractBeanDefinitionReader 的方法,使用ResourceLoader将资源文件路径转换为Resource
  使用DocumentLoader对Resource文件进行转换,将Resource文件转换为Document文件
  使用BeanDefinitionDocumentReader的实现类DefaultBeanDefinitionDocumentReader对Document进行解析,并使用BeanDefinitionParserDelegate对Element进行解析。
  持有registry(其实就是beanfactory),reader解析配置文件之后,把bean注册到beanfactory中。

 

核心方法loadBeanDefinitions:

  把编码源添加到currentResources 中
  把inputStream转换为inputSource
  使用DefaultDocumentLoader把 inputStream转换为Doucument
  使用DefaultBeanDefinitionDocumentReader解析document,把bean注册到factory

  Resource[] resources = ((ResourcePatternResolver)resourceLoader).getResources(location);
  loadCount = this.loadBeanDefinitions(resources);
  if(actualResources != null) {
    Resource[] var6 = resources;
    int var7 = resources.length;

    for(int var8 = 0; var8 < var7; ++var8) {
      Resource resource = var6[var8];
      actualResources.add(resource);
    }
  }

  return loadCount;

  一连串的调用之后,会走到这里,resource其实就是spring的xml配置文件。

  public int loadBeanDefinitions(EncodedResource encodedResource) throws BeanDefinitionStoreException {
    Set<EncodedResource> currentResources = (Set)this.resourcesCurrentlyBeingLoaded.get();
    if(currentResources == null) {
      currentResources = new HashSet(4);
      this.resourcesCurrentlyBeingLoaded.set(currentResources);
    }

    if(!((Set)currentResources).add(encodedResource)) {
      throw new BeanDefinitionStoreException("Detected cyclic loading of " + encodedResource + " - check your import definitions!");
    } else {
      int var5;
      try {
        InputStream inputStream = encodedResource.getResource().getInputStream();

        try {
          InputSource inputSource = new InputSource(inputStream);
          if(encodedResource.getEncoding() != null) {
            inputSource.setEncoding(encodedResource.getEncoding());
          }

          var5 = this.doLoadBeanDefinitions(inputSource, encodedResource.getResource());
        } finally {
          inputStream.close();
        }
      } catch (IOException var15) {
        throw new BeanDefinitionStoreException("IOException parsing XML document from " + encodedResource.getResource(), var15);
      } finally {
        ((Set)currentResources).remove(encodedResource);//目的是防止重复加载同一个配置文件
        if(((Set)currentResources).isEmpty()) {
          this.resourcesCurrentlyBeingLoaded.remove();
        }

      }

      return var5;
    }
  }

  protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource) throws BeanDefinitionStoreException {
    Document doc = this.doLoadDocument(inputSource, resource);
    return this.registerBeanDefinitions(doc, resource);
  }
  //这里的EntityResolver一般是ResourceEntityResolver(二般情况是DelegatingEntityResolver)
  protected Document doLoadDocument(InputSource inputSource, Resource resource) throws Exception {
    return this.documentLoader.loadDocument(inputSource, this.getEntityResolver(), this.errorHandler, this.getValidationModeForResource(resource), this.isNamespaceAware());
  }
  //DefaultBeanDefinitionDocumentReader解析doc,DefaultBeanDefinitionDocumentReader在第十一篇
  public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException {
    BeanDefinitionDocumentReader documentReader = this.createBeanDefinitionDocumentReader();
    int countBefore = this.getRegistry().getBeanDefinitionCount();
    // Map<String, BeanDefinition> beanDefinitionMap的size大小,所以解析后的bean都放在这里
    documentReader.registerBeanDefinitions(doc, this.createReaderContext(resource));
    return this.getRegistry().getBeanDefinitionCount() - countBefore;
  }

  具体的解析过程转接到DefaultBeanDefinitionDocumentReader的doRegisterBeanDefinitions方法中。

  关于EncodedResource,提供了reader对象,没有设置字符集和编码时,将使用默认的字符集解码。

  public Reader getReader() throws IOException {
    return this.charset != null?new InputStreamReader(this.resource.getInputStream(), this.charset):(this.encoding != null?new InputStreamReader(this.resource.getInputStream(), this.encoding):new     InputStreamReader(this.resource.getInputStream()));
  }

posted @ 2019-03-06 21:44  青青子衿J  阅读(827)  评论(0)    收藏  举报