Spring XmlFactory的代码解析(Spring源码深度解析读书笔记)

这边文章是Spring源码深度解析读书笔记的读书笔记

BeanFactory bf = new XmlBeanFactory(new ClassPathResource("org/springframework/beans/application-context.xml"));

解析该行代码调用全过程

  1. ClassPathResource将文件加载为Resource文件,通过ClassUtils获取默认的DefaultClassLoader
    XmlBeanFactory
  2. 通过调用父类DefaultListableBeanFactory,同时DefaultListableBeanFactory在调用其父类
    AbstractAutowireCapableBeanFactory的构造器,实现上述几个类的初始化,以及通过
 	ignoreDependencyInterface(BeanNameAware.class);
    ignoreDependencyInterface(BeanFactoryAware.class);
    ignoreDependencyInterface(BeanClassLoaderAware.class);
    实现忽略给定接口的自动装配功能(具体原因查阅spring源码P30)
  1. 调用XmlBeanFactory中的XmlBeanDefinitionReader的loadBeanDefinition方法来对Xml文件进行解析
    XmlBeanDefinitionReader
  2. 首先将Resource文件转换成EncodedResource文件,EncodedResource类主要用于对资源文件的编码
    进行处理,其主要的逻辑在getReader()方法中,当设置了编码属性的时候Spring会使用相应的编码作为
    输入流的编码。
  3. 在loadBeanDefinitions方法中
Set<EncodedResource> currentResources = this.resourcesCurrentlyBeingLoaded.get();
 该代码主要通过属性来记录已经加载的资源
   InputStream inputStream = encodedResource.getResource().getInputStream(); 
     该代码主要从EncodedResource的文件中获取Resource的InputStream
  1. 在doLoadBeanDefinitions方法中继续调用doLoadDocument方法,方法内部如下:
 protected Document doLoadDocument(InputSource inputSource, Resource resource) throws
    Exception {
   return this.documentLoader.loadDocument(inputSource, getEntityResolver(), 
    this.errorHandler,getValidationModeForResource(resource), isNamespaceAware());
    }
  1. 在这里首先调用了getValidationModeForResource(resource)方法去获取XML文件的验证模式(DTD/XSD),主要通过是否存在DOCTYPE来判读(true为DTD),非自动验证的模式可以通过调 用XmlBeanDefinitionReader的setValidationMode方法实现,下面是该方法的实现
 protected int getValidationModeForResource(Resource resource) {
       int validationModeToUse = getValidationMode();
       if (validationModeToUse != VALIDATION_AUTO) {
          return validationModeToUse;
       }
       int detectedMode = detectValidationMode(resource);
       if (detectedMode != VALIDATION_AUTO) {
          return detectedMode;
       }
       // Hmm, we didn't get a clear indication... Let's assume XSD,
       // since apparently no DTD declaration has been found up until
       // detection stopped (before finding the document's root tag).
       return VALIDATION_XSD;
    }
这块儿注释的意思是反正我们没得到指示,就假装是XSD吧
 int detectedMode = detectValidationMode(resource);
    这行代码调用了XmlValidationModeDetector的detectValidationMode方法去对自动验证模式下的验证方
    式做了判断

DocumentLoader:

  1. 通过6进入到DocumentLoader的实现类DefaultDocumentLoader中进行Document的加载,该方法
    中主要就是先创建DocumentBuilderFactory,再通过其创建DocumentBuilder
public Document loadDocument(InputSource inputSource, EntityResolver entityResolver,
      ErrorHandler errorHandler, int validationMode, boolean namespaceAware) throws
Exception {

   DocumentBuilderFactory factory = createDocumentBuilderFactory(validationMode,
namespaceAware);
   if (logger.isDebugEnabled()) {
      logger.debug("Using JAXP provider [" + factory.getClass().getName() + "]");
   }
   DocumentBuilder builder = createDocumentBuilder(factory, entityResolver,
errorHandler);
   return builder.parse(inputSource);
}
 DocumentBuilder builder = createDocumentBuilder(factory, entityResolver,errorHandler);
该行代码会调用下列方法

PluggableSchemaResolver

  1. 因为这次用到的是XSD验证模式,所以我们进入了EntityResolver的其中一个实现
    类PluggableSchemaResolver中调用其resolveEntity方法来下载相应的定义,以便对文档进行一个
    验证。DTD是通过BeansDtdResolver的resolveEntity来下载相应的DTD声明。

  2. 6-9都是将文件转换为Document,回到6的下一行,XmlBeanDefinitionReader的

registerBeanDefinitions方法负责提取以及注册BeanDefinition
public int registerBeanDefinitions(Document doc, Resource resource) throws
BeanDefinitionStoreException {
   //使用DefaultBeanDefinitionDocumentReader去实例化BeanDefinitionDocumentReader
   BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader();
   //记录统计前BeanDefinition的加载个数
   int countBefore = getRegistry().getBeanDefinitionCount();
   //在实例化BeanDefinitionDocumentReader时候会将BeanDefinitionRegistry传入,默认使用继承自
   DefaultBeanDefinitionDocumentReader的子类
   //加载及注册bean
   documentReader.registerBeanDefinitions(doc, createReaderContext(resource));
   //记录本次加载的BeanDefinition个数
   return getRegistry().getBeanDefinitionCount() - countBefore;
}
documentReader.registerBeanDefinitions(doc, createReaderContext(resource));
在该方法中,会去调用DefaultBeanDefinitionDocumentReader
 的documentReader.registerBeanDefinitions方法,

DefaultBeanDefinitionDocumentReader

  1. 之前都算是XML加载解析的准备阶段, registerBeanDefinitions方法中的doRegisterBeanDefinitions
    方法才算是真正地开始解析XML
preProcessXml(root);
parseBeanDefinitions(root, this.delegate);
postProcessXml(root);
pre和pos方法用于如果继承自DefaultBeanDefinitionDocumentReader的子类需要在Bean解析前后做
一些处理的话,只需要重写这两个方法就好了。par方法里通过if else 判断走默认还是自定义进行解析,代码如下:
if (delegate.isDefaultNamespace(ele)) {
   parseDefaultElement(ele, delegate);
}
else {
   delegate.parseCustomElement(ele);
}

补一下容器加载的相关类图
DefaultListableBeanFactory
在这里插入图片描述
图未完待续…
综上,xml的解析就算是完成了,默认和自定义标签的解析下次再写读书笔记吧

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值