Spring源码之 obtainFreshBeanFactory

Spring源码之 obtainFreshBeanFactory

在这里插入图片描述

在Spring IOC容器启动过程中,需要先去初始化beanFctory,这就是obtainFreshBeanFactory 方法,去读spring 的bean配置文件,将xml配置文件中的配置转换成BeanDefinition,加载到BeanFactory当中。
beabFactory初始化过程

一、首先从ClassPathXmlApplicationContext 构造方法说起

测试代码如图:

		ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");

ApplicationContext 代表 IOC容器,ClassPathXmlApplicationContext 是 ApplicationContext的实现类,该实现类从类路径下加载配置文件。

  • ClassPathXmlApplicationContext 的构造方法

ClassPathXmlApplicationContext类中构造方法:

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

    }
  • this.setConfigLocations(configLocations);

将配置文件路径赋值给configLocations,后边源码中会将配置文件解析为Resource来使用。

  • this.refresh();

调用的是父类 AbstractApplicationContext 中的refresh方法。

AbstractApplicationContext类的refresh方法:

public void refresh() throws BeansException, IllegalStateException {
        synchronized(this.startupShutdownMonitor) {
            this.prepareRefresh();
            ConfigurableListableBeanFactory beanFactory = this.obtainFreshBeanFactory();
            this.prepareBeanFactory(beanFactory);

            try {
                this.postProcessBeanFactory(beanFactory);
                this.invokeBeanFactoryPostProcessors(beanFactory);
                this.registerBeanPostProcessors(beanFactory);
                this.initMessageSource();
                this.initApplicationEventMulticaster();
                this.onRefresh();
                this.registerListeners();
                this.finishBeanFactoryInitialization(beanFactory);
                this.finishRefresh();
            } catch (BeansException var5) {
                this.logger.warn("Exception encountered during context initialization - cancelling refresh attempt", var5);
                this.destroyBeans();
                this.cancelRefresh(var5);
                throw var5;
            }

        }
    }
  • this.obtainFreshBeanFactory();

这个refresh方法中的 ConfigurableListableBeanFactory beanFactory = this.obtainFreshBeanFactory();就是我们本次要分析的重点。

AbstractApplicationContext类中的obtainFreshBeanFactory方法:

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

        return beanFactory;
    }
  • this.refreshBeanFactory();

AbstractApplicationContext是一个抽象类,this.refreshBeanFactory(); 调用的是 AbstractApplicationContext 的子 AbstractRefreshableApplicationContext中的refreshBeanFactory方法。

AbstractRefreshableApplicationContext类的refreshBeanFactory方法:

    protected final void refreshBeanFactory() throws BeansException {
    
         // 判断是否已经实例化好了beanFactory,如果实例化好了,就要做销毁和关闭。
        if (this.hasBeanFactory()) {
            this.destroyBeans();
            this.closeBeanFactory();
        }

        try {
        // 创建 DefaultListableBeanFactory 
            DefaultListableBeanFactory beanFactory = this.createBeanFactory();
            // 执行序列化id
            beanFactory.setSerializationId(this.getId());
            // 设置默认覆盖同名bean,默认允许bean之间循环依赖
            this.customizeBeanFactory(beanFactory);
            // 对xml配置文件读取和解析
            this.loadBeanDefinitions(beanFactory);
            synchronized(this.beanFactoryMonitor) {
                this.beanFactory = beanFactory;
            }
        } catch (IOException var5) {
            throw new ApplicationContextException("I/O error parsing bean definition source for " + this.getDisplayName(), var5);
        }
    }

this.loadBeanDefinitions(beanFactory); 方法中就开始对xml配置文件读取和解析的相关工作。

AbstractXmlApplicationContext 类中的 loadBeanDefinitions 方法:

    protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException {
    // 实例化 beanDefinitionReader
        XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);
        // 获取系统运行参数
        beanDefinitionReader.setEnvironment(this.getEnvironment());
        beanDefinitionReader.setResourceLoader(this);
        // 设置解析xml校验文件的 ResourceEntityResolver
        beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this));
        this.initBeanDefinitionReader(beanDefinitionReader);
        this.loadBeanDefinitions(beanDefinitionReader);
    }

this.loadBeanDefinitions(beanDefinitionReader); 最终调用的是 XmlBeanDefinitionReader 中

XmlBeanDefinitionReader类中 的 loadBeanDefinitions 方法:

public int loadBeanDefinitions(EncodedResource encodedResource) throws BeanDefinitionStoreException {
        Assert.notNull(encodedResource, "EncodedResource must not be null");
        if (this.logger.isInfoEnabled()) {
            this.logger.info("Loading XML bean definitions from " + encodedResource.getResource());
        }

        Set<EncodedResource> currentResources = (Set)this.resourcesCurrentlyBeingLoaded.get();
        if (currentResources == null) {
            currentResources = new HashSet(4);
            this.resourcesCurrentlyBeingLoaded.set(currentResources);
        }

        if (!((Set)currentResources).add(encodedResource)) {
            throw new BeanDefinitionStoreException("Detected cyclic loading of " + encodedResource + " - check your import definitions!");
        } else {
            int var5;
            try {
                InputStream inputStream = encodedResource.getResource().getInputStream();

                try {
                    InputSource inputSource = new InputSource(inputStream);
                    if (encodedResource.getEncoding() != null) {
                        inputSource.setEncoding(encodedResource.getEncoding());
                    }

					// 解析 xml 文件
                    var5 = this.doLoadBeanDefinitions(inputSource, encodedResource.getResource());
                } finally {
                    inputStream.close();
                }
            } catch (IOException var15) {
                throw new BeanDefinitionStoreException("IOException parsing XML document from " + encodedResource.getResource(), var15);
            } finally {
                ((Set)currentResources).remove(encodedResource);
                if (((Set)currentResources).isEmpty()) {
                    this.resourcesCurrentlyBeingLoaded.remove();
                }

            }

            return var5;
        }
    }

doLoadBeanDefinitions 方法

    protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource) throws BeanDefinitionStoreException {
        try {
        // 加载 xml 文件,得到 Document 
            Document doc = this.doLoadDocument(inputSource, resource);
            // 根据返回的 Document 注册Bean信息
            return this.registerBeanDefinitions(doc, resource);
        } catch (BeanDefinitionStoreException var4) {
            throw var4;
        } catch (SAXParseException var5) {
            throw new XmlBeanDefinitionStoreException(resource.getDescription(), "Line " + var5.getLineNumber() + " in XML document from " + resource + " is invalid", var5);
        } catch (SAXException var6) {
            throw new XmlBeanDefinitionStoreException(resource.getDescription(), "XML document from " + resource + " is invalid", var6);
        } catch (ParserConfigurationException var7) {
            throw new BeanDefinitionStoreException(resource.getDescription(), "Parser configuration exception parsing XML from " + resource, var7);
        } catch (IOException var8) {
            throw new BeanDefinitionStoreException(resource.getDescription(), "IOException parsing XML document from " + resource, var8);
        } catch (Throwable var9) {
            throw new BeanDefinitionStoreException(resource.getDescription(), "Unexpected exception parsing XML document from " + resource, var9);
        }
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值