资讯专栏INFORMATION COLUMN

Spring源码阅读——ClassPathXmlApplicationContext(一)

taowen / 1140人阅读

摘要:的继承关系继承了,实现了接口。是所有容器的顶级接口,中所有容器都是基于的。方法创建一个新的容器。在本方法中,最重要的是,调用这个方法解析配置文件,注册。

ClassPathXmlApplicationContext的继承关系

ClassPathXmlApplicationContext继承了AbstractXmlApplicationContext,实现了ApplicationContext接口。BeanFactory是所有容器的顶级接口,spring中所有容器都是基于BeanFactory的。ClassPathXmlApplicationContext继承关系如下图:

创建ClassPathXmlApplicationContext实例

ClassPathXmlApplicationContext中有多个构造方法,最终都通过如下的构造方法初始化容器:

public ClassPathXmlApplicationContext(
          String[] configLocations, boolean refresh, @Nullable ApplicationContext parent)
          throws BeansException {
     super(parent);
     setConfigLocations(configLocations);
     if (refresh) {
          refresh();
     }
}

其中,refresh()方法完成了容器的初始化。

refresh()方法的实现分析

refresh()方法的实现代码如下

    public void refresh() throws BeansException, IllegalStateException {
        synchronized (this.startupShutdownMonitor) {
            // 上下文刷新的准备工作,完成一下工作:
            //1、设置启动时间、是否关闭和是否激活
            //2、在上下文中初始化任何占位符属性资源
            //3、验证标记为必需的属性文件是可解析的
            prepareRefresh();

            // 创建DefaultListableBeanFactory实例,解析xml配置文件,注册bean
            ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

            //对BeanFactory进行各种功能填充
            //在此方法中,增加的支持@Qualifier与@Autowired这两个注解
            prepareBeanFactory(beanFactory);

            try {
                // 由子类实现,可进行自定义扩展
                postProcessBeanFactory(beanFactory);

                // 激活BeanFactory的处理器
                invokeBeanFactoryPostProcessors(beanFactory);

                // Register bean processors that intercept bean creation.
                registerBeanPostProcessors(beanFactory);

                // 初始化message资源
                initMessageSource();

                // 为这个context初始化一个事件广播器
                initApplicationEventMulticaster();

                // 由子类实现,初始化其他bean
                onRefresh();

                // 注册已实现ApplicationListener接口的Bean
                registerListeners();

                // 实例化所有非延迟初始化的单例模式bean
                finishBeanFactoryInitialization(beanFactory);

                // 完成刷新过程,通知生命周期处理器lifecycleProcessor刷新过程,同时发出ContextRefreshEvent通知监听者
                finishRefresh();
            }

            catch (BeansException ex) {
                if (logger.isWarnEnabled()) {
                    logger.warn("Exception encountered during context initialization - " +
                            "cancelling refresh attempt: " + ex);
                }

                // Destroy already created singletons to avoid dangling resources.
                destroyBeans();

                // Reset "active" flag.
                cancelRefresh(ex);

                // Propagate exception to caller.
                throw ex;
            }

            finally {
                // Reset common introspection caches in Spring"s core, since we
                // might not ever need metadata for singleton beans anymore...
                resetCommonCaches();
            }
        }
    }
obtainFreshBeanFactory()方法的实现

此方法主要作用是创建DefaultListableBeanFactory实例,解析xml配置文件,注册bean。内部调用了调用了AbstractRefreshableApplicationContext类的refreshBeanFactory()方法创建bean工厂。refreshBeanFactory()方法实现如下:

protected final void refreshBeanFactory() throws BeansException {
        //如果beanfactory存在,销毁所以bean和关闭beanfactory
        if (hasBeanFactory()) {
            destroyBeans();
            closeBeanFactory();
        }
        try {
            //定义beanFactory
            DefaultListableBeanFactory beanFactory = createBeanFactory();
            beanFactory.setSerializationId(getId());
            customizeBeanFactory(beanFactory);
            //将bean解析为BeanDefinition
            loadBeanDefinitions(beanFactory);
            synchronized (this.beanFactoryMonitor) {
                this.beanFactory = beanFactory;
            }
        }
        catch (IOException ex) {
            throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
        }
    }

refreshBeanFactory()方法中,首先判断是否存在beanfactory,如果存在,销毁所有Bean,关闭beanfactory。createBeanFactory()方法创建一个新的容器。在本方法中,最重要的是loadBeanDefinitions(beanFactory),调用这个方法解析xml配置文件,注册bean。

loadBeanDefinitions(beanFactory)方法的实现如下
protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException {
        // 根据给定的BeanFactory创建一个新的 XmlBeanDefinitionReader
        XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);

        // 根据上下文配置bean definition reader
        beanDefinitionReader.setEnvironment(this.getEnvironment());
        beanDefinitionReader.setResourceLoader(this);
        beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this));
        initBeanDefinitionReader(beanDefinitionReader);
        //通过beanDefinitionReader解析xml配置文件,注册bean
        loadBeanDefinitions(beanDefinitionReader);
    }

在XmlBeanDefinitionReader中实现了loadBeanDefinitions(beanDefinitionReader)方法,代码如下:

//省略了异常处理相关代码,主要逻辑如下
public int loadBeanDefinitions(EncodedResource encodedResource) throws BeanDefinitionStoreException {
        //从encodedResource中得到InputSource和Resource
        Set currentResources = this.resourcesCurrentlyBeingLoaded.get();
        InputStream inputStream = encodedResource.getResource().getInputStream();
        InputSource inputSource = new InputSource(inputStream);
        if (encodedResource.getEncoding() != null) {
            inputSource.setEncoding(encodedResource.getEncoding());
        }
         //调用此方法加载BeanDefinition
        return doLoadBeanDefinitions(inputSource, encodedResource.getResource());
    }

doLoadBeanDefinitions(inputSource, encodedResource.getResource())中,从资源文件中读取Document,并且调用registerBeanDefinitions(doc, resource)注册BeanDefinition,省略无关代码,实现如下:

protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource)
            throws BeanDefinitionStoreException {
        try {
            //从resource中读取得到Document
            Document doc = doLoadDocument(inputSource, resource);
            //注册BeanDefinition
            return registerBeanDefinitions(doc, resource);
        }
        catch (BeanDefinitionStoreException ex) {
            throw ex;
        }
}

在registerBeanDefinitions(doc, resource)方法中,BeanDefinition的注册时委托给BeanDefinitionDocumentReader的registerBeanDefinitions(doc, createReaderContext(resource))方法进行注册的。

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/69654.html

相关文章

  • Spring源码阅读——ClassPathXmlApplicationContext(四)

    摘要:在的方法中,遍历每一个节点,判断是否为默认命名空间中的节点,如果是非默认命名空间的,调用方法进行处理。在学习自定义标签解析之前,先写一个自定义标签的。 在DefaultBeanDefinitionDocumentReader的parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate)方法中,遍历每一...

    silenceboy 评论0 收藏0
  • Spring源码阅读——ClassPathXmlApplicationContext(四)

    摘要:在的方法中,遍历每一个节点,判断是否为默认命名空间中的节点,如果是非默认命名空间的,调用方法进行处理。在学习自定义标签解析之前,先写一个自定义标签的。 在DefaultBeanDefinitionDocumentReader的parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate)方法中,遍历每一...

    wmui 评论0 收藏0
  • Spring源码阅读——ClassPathXmlApplicationContext(四)

    摘要:在的方法中,遍历每一个节点,判断是否为默认命名空间中的节点,如果是非默认命名空间的,调用方法进行处理。在学习自定义标签解析之前,先写一个自定义标签的。 在DefaultBeanDefinitionDocumentReader的parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate)方法中,遍历每一...

    ixlei 评论0 收藏0
  • Spring源码阅读——ClassPathXmlApplicationContext(三)

    摘要:在上一篇源码阅读二文章的最后,需要解析元素,创建实例完成必须的装配和进行最终的注册来完成元素的解析和注册,下面分别阅读三步的源码。 在上一篇Spring源码阅读——ClassPathXmlApplicationContext(二)文章的最后,需要解析bean元素,创建BeanDefinitionHolder实例、完成必须的装配和进行最终的注册bean来完成bean元素的解析和注册,下面...

    xbynet 评论0 收藏0
  • Spring源码阅读——ClassPathXmlApplicationContext(三)

    摘要:在上一篇源码阅读二文章的最后,需要解析元素,创建实例完成必须的装配和进行最终的注册来完成元素的解析和注册,下面分别阅读三步的源码。 在上一篇Spring源码阅读——ClassPathXmlApplicationContext(二)文章的最后,需要解析bean元素,创建BeanDefinitionHolder实例、完成必须的装配和进行最终的注册bean来完成bean元素的解析和注册,下面...

    AndroidTraveler 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<