• spring源码-增强容器xml解析-3.1


      一、ApplicationContext的xml解析工作是通过ClassPathXmlApplicationContext来实现的,其实看过ClassPathXmlApplicationContext的xml源码解析过程的其实都应该知道,xml的解析过程基本上就是用原来的XmlBeanFactory的解析过程完成的。

      二、为什么要拿出来单独说一下呢,其目的就是,了解怎么用同样的方式来实现xml解析过程。

      三、xml解析过程是通过refresh下的obtainFreshBeanFactory函数实现,所以这里重点讲解obtainFreshBeanFactory的实现过程。

      四、xml源码解析:obtainFreshBeanFactory

      1)开端

        protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
            //解析过程
            this.refreshBeanFactory();
            //这里的beanFactory就是DefaultListableBeanFactory(后续会讲到)
            ConfigurableListableBeanFactory beanFactory = this.getBeanFactory();
            if (this.logger.isDebugEnabled()) {
                this.logger.debug("Bean factory for " + this.getDisplayName() + ": " + beanFactory);
            }
            return beanFactory;
        }

      2)refreshBeanFactory

        protected final void refreshBeanFactory() throws BeansException {
            if (this.hasBeanFactory()) {
                this.destroyBeans();
                this.closeBeanFactory();
            }
    
            try {
                //是不是很熟悉,这里也是通过DefaultListableBeanFactory的方式来实现的
                DefaultListableBeanFactory beanFactory = this.createBeanFactory();
                beanFactory.setSerializationId(this.getId());
                //自定义beanFactory,处理循环依赖
                //主要作用设置@Autowired和@Qualifier解析器QualifierAnnotationAutowireCandidateResolver
                this.customizeBeanFactory(beanFactory);
                //xml解析过程
                this.loadBeanDefinitions(beanFactory);
                Object var2 = this.beanFactoryMonitor;
                synchronized(this.beanFactoryMonitor) {
                    this.beanFactory = beanFactory;
                }
            } catch (IOException var4) {
                throw new ApplicationContextException("I/O error parsing bean definition source for " + this.getDisplayName(), var4);
            }
        }

      a、DefaultListableBeanFactory继承关系

      这里其实就可以看出ConfigurableListableBeanFactory就是这里的DefaultListableBeanFactory

      b、customizeBeanFactory(这里不详细介绍注解的解析过程)

        protected void customizeBeanFactory(DefaultListableBeanFactory beanFactory) {
            if (this.allowBeanDefinitionOverriding != null) {
                beanFactory.setAllowBeanDefinitionOverriding(this.allowBeanDefinitionOverriding.booleanValue());
            }
    
            if (this.allowCircularReferences != null) {
                beanFactory.setAllowCircularReferences(this.allowCircularReferences.booleanValue());
            }
    
            beanFactory.setParameterNameDiscoverer(new LocalVariableTableParameterNameDiscoverer());
            beanFactory.setAutowireCandidateResolver(new QualifierAnnotationAutowireCandidateResolver());
        }

      c、loadBeanDefinitions

        protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException {
            //是不是又很熟悉,还是基于XmlBeanDefinitionReader来进行解析了
            XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);
            beanDefinitionReader.setResourceLoader(this);
            beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this));
            //解析xml
            this.initBeanDefinitionReader(beanDefinitionReader);
            this.loadBeanDefinitions(beanDefinitionReader);
        }
        protected void loadBeanDefinitions(XmlBeanDefinitionReader reader) throws BeansException, IOException {
            Resource[] configResources = this.getConfigResources();
            if (configResources != null) {
                reader.loadBeanDefinitions(configResources);
            }
            //这里是配置方式不一样,我们是通过configLocations进行配置
            String[] configLocations = this.getConfigLocations();
            if (configLocations != null) {
                //解析文件
                reader.loadBeanDefinitions(configLocations);
            }
    
        }
        public int loadBeanDefinitions(String... locations) throws BeanDefinitionStoreException {
            Assert.notNull(locations, "Location array must not be null");
            int counter = 0;
            String[] var6 = locations;
            int var5 = locations.length;
    
            for(int var4 = 0; var4 < var5; ++var4) {
                String location = var6[var4];
           //主要目的计数 counter
    += this.loadBeanDefinitions(location); } return counter; }
      public int loadBeanDefinitions(String location) throws BeanDefinitionStoreException {
            return this.loadBeanDefinitions(location, (Set)null);
        }
    
        public int loadBeanDefinitions(String location, Set<Resource> actualResources) throws BeanDefinitionStoreException {
            ResourceLoader resourceLoader = this.getResourceLoader();
            if (resourceLoader == null) {
                throw new BeanDefinitionStoreException("Cannot import bean definitions from location [" + location + "]: no ResourceLoader available");
            } else {
                int loadCount;
                if (!(resourceLoader instanceof ResourcePatternResolver)) {
                    Resource resource = resourceLoader.getResource(location);
                    loadCount = this.loadBeanDefinitions((Resource)resource);
                    if (actualResources != null) {
                        actualResources.add(resource);
                    }
    
                    if (this.logger.isDebugEnabled()) {
                        this.logger.debug("Loaded " + loadCount + " bean definitions from location [" + location + "]");
                    }
    
                    return loadCount;
                } else {
                    try {
                        Resource[] resources = ((ResourcePatternResolver)resourceLoader).getResources(location);
                        //包装成Resource,进行解析
                        loadCount = this.loadBeanDefinitions(resources);
                        if (actualResources != null) {
                            Resource[] var9 = resources;
                            int var8 = resources.length;
    
                            for(int var7 = 0; var7 < var8; ++var7) {
                                Resource resource = var9[var7];
                                actualResources.add(resource);
                            }
                        }
    
                        if (this.logger.isDebugEnabled()) {
                            this.logger.debug("Loaded " + loadCount + " bean definitions from location pattern [" + location + "]");
                        }
    
                        return loadCount;
                    } catch (IOException var10) {
                        throw new BeanDefinitionStoreException("Could not resolve bean definition resource pattern [" + location + "]", var10);
                    }
                }
            }
        }
        public int loadBeanDefinitions(Resource... resources) throws BeanDefinitionStoreException {
            Assert.notNull(resources, "Resource array must not be null");
            int counter = 0;
            Resource[] var6 = resources;
            int var5 = resources.length;
    
            for(int var4 = 0; var4 < var5; ++var4) {
                Resource resource = var6[var4];
                //单独解析没一个resource
                counter += this.loadBeanDefinitions((Resource)resource);
            }
    
            return counter;
        }

      d、loadBeanDefinitions(这里是不是很熟悉,这里的解析过程就是XmlBeanFactory里面的xml的核心解析过程)

    public int loadBeanDefinitions(Resource resource) throws BeanDefinitionStoreException {
            return this.loadBeanDefinitions(new EncodedResource(resource));
        }
    
        public int loadBeanDefinitions(EncodedResource encodedResource) throws BeanDefinitionStoreException {
            Assert.notNull(encodedResource, "EncodedResource must not be null");
            if (this.logger.isInfoEnabled()) {
                this.logger.info("Loading XML bean definitions from " + encodedResource.getResource());
            }
    
            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 var6;
                try {
                    InputStream inputStream = encodedResource.getResource().getInputStream();
    
                    try {
                        InputSource inputSource = new InputSource(inputStream);
                        if (encodedResource.getEncoding() != null) {
                            inputSource.setEncoding(encodedResource.getEncoding());
                        }
    
                        var6 = 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 var6;
            }
        }

      e、剩下的部分参考:https://www.cnblogs.com/ll409546297/p/9451784.html的源码解析部分第4)点

      五、分析一下流程

      1)通过ClassPathXmlApplicationContext来进行xml的解析工作

      2)首先进行赋值到configLocations的属性上面

      3)xml解析过程还是通过XmlBeanDefinitionReader来实现解析

      4)xml解析不同的地方:

      a、新增解析增加计数

      b、返回类型使用接口ConfigurableListableBeanFactory

      c、增加string的配置方式,代码编写感觉更好。

      d、解析之前和之后,都做了很多其他工作。相比之下拓展了很多其他功能。

  • 相关阅读:
    JS的toFixed方法设置小数点位数后再进行计算,数据出错问题
    表单input项使用label,同时引用Bootstrap库,导致input点击效果区增大
    表单多文件上传样式美化 && 支持选中文件后删除相关项
    Fiddler使用AutoResponder进行本地文件和线上文件的映射
    ES6笔记(7)-- Promise异步编程
    ES6笔记(6)-- Set、Map结构和Iterator迭代器
    ES6笔记(5)-- Generator生成器函数
    ES6笔记(4)-- Symbol类型
    ES6笔记(3)-- 解构赋值
    ES6笔记(2)-- let的块级作用域
  • 原文地址:https://www.cnblogs.com/ll409546297/p/9493472.html
Copyright © 2020-2023  润新知