zoukankan      html  css  js  c++  java
  • IOC第一部分篇一:xml文件的解析预处理

    我们在main函数中从一行代码开始分析:

    ConfigurableListableBeanFactory beanFactory = new XmlBeanFactory(new ClassPathResource("spring.xml"));

    大多数人可能会有疑问,现在加载XML文件不是通过:

    ApplicationContext ctx = new ClassPathXmlApplicationContext("spring.xml"); spring应用上下文来加载和操作XML文档的吗?没错,在spring2.5版本的时候还没有spring应用上下文对象,这个是spring在版本spring3以后加了ApplicationContext 对象,这个对象包含了 XmlBeanFactory对象的所有功能,对其进行了扩展。我们先分析 XmlBeanFactory的解析流程。

    1.1 配置文件的封装

    Spring是通过ClassPathResource对象进行封装。ClassPathResource对象实现esource接口,Resource接口对象封装了所有Spring内部使用到的底层资源:FileURLClassPath等。它定义了三个判断当前 资源状态方法:存在性(exists)、可读性(isReadable)、是否处于打开状态(isOpen)。对于不同来源的资源文件都有对应的实现:文件(FileSystemResource)ClassPath资源(ClassPathResource)URL资源(UrlResource)、InputStream资源(InputStreamResource)等。有了Resource接口可以对资源文件进行统一的处理了。当Resoure完成了对配置文件的封装后配置文件的读取工作就全权交给XmlBeanDefineReader来处理了。

    new ClassPathResource("spring.xml") 来完成资源文件的封装.通过XmlBeanFactory的构造函数来完成数据的加载:

    public XmlBeanFactory(Resource resource) throws BeansException {
    
    this(resource, null);
    
    }
    
     
    
    /**
    
     * Create a new XmlBeanFactory with the given input stream,
    
     * which must be parsable using DOM.
    
     * @param resource XML resource to load bean definitions from
    
     * @param parentBeanFactory parent bean factory
    
     * @throws BeansException in case of loading or parsing errors
    
     */
    
    public XmlBeanFactory(Resource resource, BeanFactory parentBeanFactory) throws BeansException {
    
    super(parentBeanFactory);
    
    this.reader.loadBeanDefinitions(resource);
    
    }

    this.reader.loadBeanDefinitions(resource)才是加载资源文件的最终实现。Reader指的就是XmlBeanDefineReader。

    打开super(parentBeanFactory)方法:

    /**
         * Create a new AbstractAutowireCapableBeanFactory.
         */
        public AbstractAutowireCapableBeanFactory() {
            super();
            ignoreDependencyInterface(BeanNameAware.class);
            ignoreDependencyInterface(BeanFactoryAware.class);
            ignoreDependencyInterface(BeanClassLoaderAware.class);
        }

    ignoreDependencyInterface方法的作用:主要是忽略给定接口的自动装配功能。举列来说:当A中有属性B,那么spring是初始化的时候,如果B没有初始化则会先初始化B。但是,当B实现了BeanNameWare接口的时候,就会进行忽略装配。

    1.2 资源文件的处理

     封装Resource对象。代码如下:

    @Override
        public int loadBeanDefinitions(Resource resource) throws BeanDefinitionStoreException {
            return loadBeanDefinitions(new EncodedResource(resource));
        }

    new EncodedResource(resource)的作用是对资源文件进行编码处理的,当设置了编码属性的时候Spring会使用相应的编码作为输入流的编码。主要体现在EncodedResource的方法上:

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

    当构造好EncodedResource对象以后进入:

    /**
         * Load bean definitions from the specified XML file.
         * @param encodedResource the resource descriptor for the XML file,
         * allowing to specify an encoding to use for parsing the file
         * @return the number of bean definitions found
         * @throws BeanDefinitionStoreException in case of loading or parsing errors
         */
        public int loadBeanDefinitions(EncodedResource encodedResource) throws BeanDefinitionStoreException {
            Assert.notNull(encodedResource, "EncodedResource must not be null");
            if (logger.isInfoEnabled()) {
                logger.info("Loading XML bean definitions from " + encodedResource.getResource());
            }
            // 通过属性记录已经加载的资源,每次加载前先判断是否已经加载过,如果已经加载过则无需重复加载,退出循环。
            Set<EncodedResource> currentResources = this.resourcesCurrentlyBeingLoaded.get();
            if (currentResources == null) {
                currentResources = new HashSet<EncodedResource>(4);
                this.resourcesCurrentlyBeingLoaded.set(currentResources);
            }
            if (!currentResources.add(encodedResource)) {
                throw new BeanDefinitionStoreException(
                        "Detected cyclic loading of " + encodedResource + " - check your import definitions!");
            }
            try {
                // 从EncodedResource对象获取Resource对象的inputstream
                InputStream inputStream = encodedResource.getResource().getInputStream();
                try {
               // inputSource不是spring的类,他的类路径是org.xml.sax.InputSource
                    InputSource inputSource = new InputSource(inputStream);
                    if (encodedResource.getEncoding() != null) {
                  // 如果设置的有编码,则使用设置的编码作为读取资源文件的流编码                  
    inputSource.setEncoding(encodedResource.getEncoding());
    } return doLoadBeanDefinitions(inputSource, encodedResource.getResource()); } finally { inputStream.close(); } } catch (IOException ex) { throw new BeanDefinitionStoreException( "IOException parsing XML document from " + encodedResource.getResource(), ex); } finally { currentResources.remove(encodedResource); if (currentResources.isEmpty()) { this.resourcesCurrentlyBeingLoaded.remove(); } }
  • 相关阅读:
    20141124-JS函数
    20141124-JS 变量,数据类型
    20141124-HTML-JavaScrilpt
    ●查询语句
    ●SQL2008基础
    ●数据库入门、更改验证方式
    ●枚举、递归
    ●值类型、引用类型
    小游戏●两人对战
    小游戏●贪吃蛇1(利用二维数组制作)
  • 原文地址:https://www.cnblogs.com/histlyb/p/8975603.html
Copyright © 2011-2022 走看看