解析Spring源码(4)--XmlBeanDefinitionReader

来源:互联网 发布:股票移动买卖软件 编辑:程序博客网 时间:2024/06/05 17:59

上两节对XmlBeanFactory和XmlBeanDefinitionReader对象reader进行了一些介绍,下面我们继续回到XmlBeanFactory中解析源码!

    public XmlBeanFactory(Resource resource, BeanFactory parentBeanFactory) throws BeansException {        super(parentBeanFactory);        this.reader.loadBeanDefinitions(resource);    }

在(2)中我们解析到这一步!

继续Debug…

进入XmlBeanDefinitionReader

    @Override    public int loadBeanDefinitions(Resource resource) throws BeanDefinitionStoreException {        return loadBeanDefinitions(new EncodedResource(resource));    }
  • new EncodedResource(resource)创建EncodedResource对象,封装resource
    /**     * 构造函数     * 创建EncodedResource对象     * Create a new {@code EncodedResource} for the given {@code Resource},     * not specifying an explicit encoding or {@code Charset}.     * @param resource the {@code Resource} to hold (never {@code null})     */    public EncodedResource(Resource resource) {        this(resource, null, null);    }    //初始化属性resource  private final Resource resource;    private EncodedResource(Resource resource, String encoding, Charset charset) {        super();        Assert.notNull(resource, "Resource must not be null");        this.resource = resource;        this.encoding = encoding;        this.charset = charset;    }
    /**     * 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());        }        //ThreadLocal对象,具体作用未知。。。???        Set<EncodedResource> currentResources = this.resourcesCurrentlyBeingLoaded.get();        if (currentResources == null) {            currentResources = new HashSet<>(4);//创建集合            this.resourcesCurrentlyBeingLoaded.set(currentResources);        }        //保存添加Resource        if (!currentResources.add(encodedResource)) {            throw new BeanDefinitionStoreException(                    "Detected cyclic loading of " + encodedResource + " - check your import definitions!");        }        try {            //通过封装resource的EncodedResource对象获取xml文档输入流            InputStream inputStream = encodedResource.getResource().getInputStream();            try {                //封装输入流                InputSource inputSource = new InputSource(inputStream);                if (encodedResource.getEncoding() != null) {//是null                    inputSource.setEncoding(encodedResource.getEncoding());                }                //加载bean                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();            }        }    }

获取输入流:
还记得当初创建的new ClassPathResource(“bean_test.xml”)对象吗?
对象类中的getInputStream()方法,通过类加载器来获取输入流。。。

    /**     * 获取xml文件的输入流     * This implementation opens an InputStream for the given class path resource.     * @see java.lang.ClassLoader#getResourceAsStream(String)     * @see java.lang.Class#getResourceAsStream(String)     */    @Override    public InputStream getInputStream() throws IOException {        InputStream is;        if (this.clazz != null) {            is = this.clazz.getResourceAsStream(this.path);        }        else if (this.classLoader != null) {            //通过类加载器获取输入流,并返回            is = this.classLoader.getResourceAsStream(this.path);        }        else {            is = ClassLoader.getSystemResourceAsStream(this.path);        }        if (is == null) {            throw new FileNotFoundException(getDescription() + " cannot be opened because it does not exist");        }        return is;    }

那么,随后InputSource是如何封装输入流的呢?

看看InputSource类吧!

public class InputSource 很简单的一个类    private InputStream byteStream;    public InputSource (InputStream byteStream)    {        setByteStream(byteStream);    }    public void setByteStream (InputStream byteStream)    {        this.byteStream = byteStream;    }

封装了输入流

继续往下解析源码:

//加载bean                return doLoadBeanDefinitions(inputSource, encodedResource.getResource());
    /**     * Actually load bean definitions from the specified XML file.     * @param inputSource the SAX InputSource to read from     * @param resource the resource descriptor for the XML file     * @return the number of bean definitions found     * @throws BeanDefinitionStoreException in case of loading or parsing errors     * @see #doLoadDocument     * @see #registerBeanDefinitions     */    protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource)            throws BeanDefinitionStoreException {        try {            //获取Document对象用于解析xml文档,包含xml文档的一些相关信息            Document doc = doLoadDocument(inputSource, resource);            //注册bean,创建是当获取的时候创建getBean("...");            return registerBeanDefinitions(doc, resource);        }        catch (BeanDefinitionStoreException ex) {            throw ex;        }        catch (SAXParseException ex) {            throw new XmlBeanDefinitionStoreException(resource.getDescription(),                    "Line " + ex.getLineNumber() + " in XML document from " + resource + " is invalid", ex);        }        catch (SAXException ex) {            throw new XmlBeanDefinitionStoreException(resource.getDescription(),                    "XML document from " + resource + " is invalid", ex);        }        catch (ParserConfigurationException ex) {            throw new BeanDefinitionStoreException(resource.getDescription(),                    "Parser configuration exception parsing XML from " + resource, ex);        }        catch (IOException ex) {            throw new BeanDefinitionStoreException(resource.getDescription(),                    "IOException parsing XML document from " + resource, ex);        }        catch (Throwable ex) {            throw new BeanDefinitionStoreException(resource.getDescription(),                    "Unexpected exception parsing XML document from " + resource, ex);        }    }
0 0