Spring IOC源码之Bean的注册过程讲解

BeanDefition加载注册过程

进入obtainFreshBeanFactory方法,这里面refreshBeanFactory方法会去创建beanFactory并加载bean

进入obtainFreshBeanFactory方法,这里面refreshBeanFactory方法会去创建beanFactory并加载bean

protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
        refreshBeanFactory();
        ConfigurableListableBeanFactory beanFactory = getBeanFactory();
        if (logger.isDebugEnabled()) {
            logger.debug("Bean factory for " + getDisplayName() + ": " + beanFactory);
        }
        return beanFactory;
    }

​进入AbstractRefreshableApplicationContext类中的refreshBeanFactory方法

在这里首先会将已经创建的bean工程销毁,然后创建新的bean工厂,设置bean工厂的一些属性,这里我们看到bean工厂是可以被序列化的,在customizeBeanFactory里面自定义bean工厂环境,通过allowBeanDefinitionOverriding和allowCircularReferences这两个属性用户可以自己来决定是否需要bean的覆盖,是否需要循环依赖,目前还暂时还用不到这两个属性,下面往容器中注册这些bean的时候会用到,loadBeanDefinitions这个方法才会去真正加载bean

protected final void refreshBeanFactory() throws BeansException {
        //如果之前已经创建了bean工厂,那么则销毁
        if (hasBeanFactory()) {
            destroyBeans();
            closeBeanFactory();
        }
        try {
            //创建bean工厂
            DefaultListableBeanFactory beanFactory = createBeanFactory();
            //设置序列化id
            beanFactory.setSerializationId(getId());
            //相同名称的bean是否允许覆盖,是否允许循环依赖
            customizeBeanFactory(beanFactory);
            //这里到了最关键的部分,将BeanDefinition加载到bean工厂
            loadBeanDefinitions(beanFactory);
            synchronized (this.beanFactoryMonitor) {
                this.beanFactory = beanFactory;
            }
        }
        catch (IOException ex) {
            throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
        }
    }

进入AbstractXmlApplicationContext类的loadBeanDefinitions方法,在这里首先给bean工厂创建一个bean资源加载器并初始化相关环境,进入loadBeanDefinitions继续加载bean,这里也是最关键的地方

protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException {
        // Create a new XmlBeanDefinitionReader for the given BeanFactory.
        //给bean工厂创建一个资源加载器
        XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);

        // Configure the bean definition reader with this context's
        // resource loading environment.
        //设置资源加载环境
        beanDefinitionReader.setEnvironment(this.getEnvironment());
        beanDefinitionReader.setResourceLoader(this);
        beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this));

        // Allow a subclass to provide custom initialization of the reader,
        // then proceed with actually loading the bean definitions.
        //初始化bean资源加载器
        initBeanDefinitionReader(beanDefinitionReader);
        //开始加载bean定义
        loadBeanDefinitions(beanDefinitionReader);
    }

它会将所有的xml进行循环加载,最终会进入XmlBeanDefinitionReader这个类里的loadBeanDefinitions方法.在这里会获得一个inputStream输入流进入doLoadBeanDefinitions方法开始读取bean,并将xml转换为Document对象

    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<>(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 {
                InputSource inputSource = new InputSource(inputStream);
                if (encodedResource.getEncoding() != 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();
            }
        }
    }

进入doLoadBeanDefinitions方法,这里主要是读取xml并转换为Document对象,关于xml的解析这个就不多介绍,直接进入到registerBeanDefinitions方法在这里开始往容器中注册bean,

    protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource)
            throws BeanDefinitionStoreException {
        try {
            //加载解析xml文件并返回一个document对象
            Document doc = doLoadDocument(inputSource, resource);
            //开始注册bean定义
            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);
        }
    }

最终会进入DefaultBeanDefinitionDocumentReader类里的parseBeanDefinitions方法,在parseDefaultElement方法会解析在xml中常见的import,alias,bean等标签

收藏 (0)
评论列表
正在载入评论列表...
我是有底线的
为您推荐
    暂时没有数据