美文网首页
Spring源码学习系列(一)之初探xml解析

Spring源码学习系列(一)之初探xml解析

作者: just_like_you | 来源:发表于2019-06-27 15:18 被阅读0次

1、从简单的xml解析bean开始

BeanFactory factory = new BeanFactory(new ClassPathResource("beans.xml"));
YourBean bean = factory.getBean(YourBean.class);

1.1、上面一共做了两个比较重要的动作

  • 加载beans.xml配置文件
  • 构造BeanFactory

1.2、怎么加载*.xml配置文件?

ClassPathResourceResource的一个实现类,而Resource是Spring的一个对java底层URL的增强抽象,里面包括是否可读,还有转化为URL,File等方法。在ClassPathResource中是通过类加载来加载类路径下的资源,而FileSystemResource是直接通过FileIntputStream来获取文件资源。

Resource抽象方法

1.3、BeanFactory的构造、初始化过程

  • XmlBeanFactory构造器


    构造器情况
  • 在调用父类的构造器的时候会设置忽略的Bean信息,这里的IgnoreDependencyInterface(xxx.class)的作用是将实现xxx.class的实现类(图中的BeanNameAware.class..)中的含有该接口的setter包含的属性的值忽略自动注入,如图1-1,将自动忽略BeanNameAware子类中BeanName属性的自动注入
    忽略bean注入信息
1-1
  • 委托给XmlBeanDefinitionReader.loadBeanDefinitions(Resource)来进行加载配置信息
  • 使用EncodeResourceResource进行编码包装
    @Override
    public int loadBeanDefinitions(Resource resource) throws BeanDefinitionStoreException {
        return loadBeanDefinitions(new EncodedResource(resource));
    }
  • 进行解析准备阶段
    public int loadBeanDefinitions(EncodedResource encodedResource) throws BeanDefinitionStoreException {
  .....校验
              // 将资源绑定到当前线程
        Set<EncodedResource> currentResources = this.resourcesCurrentlyBeingLoaded.get();
        if (currentResources == null) {
            currentResources = new HashSet<>(4);
            this.resourcesCurrentlyBeingLoaded.set(currentResources);
        }
        if (!currentResources.add(encodedResource)) {
            throw new BeanDefinitionStoreException(
                    "Detected cyclic loading of " + encodedResource + " - check your import definitions!");
        }
        try {
              
            InputStream inputStream = encodedResource.getResource().getInputStream();
            try {
  //这里会将Resource的输入流拿到然后转化为xml中的IntputSource
                InputSource inputSource = new InputSource(inputStream);
                if (encodedResource.getEncoding() != null) {
                    inputSource.setEncoding(encodedResource.getEncoding());
                }
    //执行加载的主要逻辑
                return doLoadBeanDefinitions(inputSource, encodedResource.getResource());
            }
    .....关闭资源
    }
  • 进行到处理加载xml配置的主方法
protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource)
            throws BeanDefinitionStoreException {

        try {
                  //  SAX解析为xml的Document对象
            Document doc = doLoadDocument(inputSource, resource);
                  // 注册BeanDefinition并返回数量
            int count = registerBeanDefinitions(doc, resource);
            if (logger.isDebugEnabled()) {
                logger.debug("Loaded " + count + " bean definitions from " + resource);
            }
            return count;
        }
        
  • 其中doLoadDocument()源码
    当中主要getValidationModeForResource会根据传递的xml的解析方法(DTD,XSD)来校验当前文件的格式是否正确
    getEntityResolver()主要是避免网络获取(DTD,XSD)的标准文件,通过本地文件系统(DTD)或META-INF/spring.factories(XSD)下来加快程序的运行
    protected Document doLoadDocument(InputSource inputSource, Resource resource) throws Exception {
        return this.documentLoader.loadDocument(inputSource, getEntityResolver(), this.errorHandler,
                getValidationModeForResource(resource), isNamespaceAware());
    }
  • 然后就是通过DocumentBuilderFactory来进行标准的SAX解析,从而获取到配置文件的Document对象
    标准sax解析

完结,下一章注册BeanDefinition

相关文章

网友评论

      本文标题:Spring源码学习系列(一)之初探xml解析

      本文链接:https://www.haomeiwen.com/subject/cwxrcctx.html