解析Spring源码(4)--XmlBeanDefinitionReader

上两节对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);
        }
    }
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值