美文网首页
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