zoukankan      html  css  js  c++  java
  • ApplicationContext(三)BeanFactory 初始化

    ApplicationContext(三)BeanFactory 初始化

    上节我们提到容器初始化的第一步首先进行了属性的检验,下面就要开始第二步:进行 beanFactory 的初始化工作了。

    ApplicationContext 是对 BeanFactory 的功能上的扩展,不但包含了 BeanFactory 的全部功能更在其基础上添加了大量的扩展应用,那么 obtainFreshBeanFactory 正是实现 BeanFactory ,并对配置文件进行解析。

    源代码【AbstractApplicationContext】

    protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
        // 初始化 BeanFactory,并进行 XML 文件读取,并将得到的 BeanFactory 记录在当前实体的属性中
        refreshBeanFactory();
        // 返回当前实体的 BeanFactory 属性
        ConfigurableListableBeanFactory beanFactory = getBeanFactory();
        return beanFactory;
    }
    

    很明显这段代码没有做什么事,将其主要的工作都委托给了 refreshBeanFactory() 方法,这个方法由其子类实现。

    源代码【AbstractRefreshableApplicationContext】

    protected final void refreshBeanFactory() throws BeansException {
        if (hasBeanFactory()) {
            destroyBeans();
            closeBeanFactory();
        }
        try {
            // 1. 创建 DefaultListableBeanFactory
            DefaultListableBeanFactory beanFactory = createBeanFactory();
    
            // 为了序列化指定id,如果需要的话,让这个 beanFactory 从 id 反序列化到 BeanFactory 对象
            beanFactory.setSerializationId(getId());
            // 2. 定制 beanFactory,如设置:①是否允许同名覆盖、②是否允许循环依赖
            customizeBeanFactory(beanFactory);
            // 3. 初始化 DocumentReader,并进行 XML 文件读取及解析
            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() 方法中主要做了三件事:

    (1) 创建 BeanFactory。创建前需要先销毁以前的 beanFactory。

    (2) 定制 BeanFactory。设置了是否允许同名覆盖、是否允许循环依赖两个属性。你可能会奇怪,这两个属性本来就是 null,没有值,这是在干什么?还是那名话,需要子类来覆盖。

    (3) 加载 BeanFactory 配置文件。解析 xml 文件,加载 BeanDefinition。

    一、创建 BeanFactory

    protected DefaultListableBeanFactory createBeanFactory() {
        return new DefaultListableBeanFactory(getInternalParentBeanFactory());
    }
    

    二、定制 BeanFactory

    protected void customizeBeanFactory(DefaultListableBeanFactory beanFactory) {
        if (this.allowBeanDefinitionOverriding != null) {
            beanFactory.setAllowBeanDefinitionOverriding(this.allowBeanDefinitionOverriding);
        }
        if (this.allowCircularReferences != null) {
            beanFactory.setAllowCircularReferences(this.allowCircularReferences);
        }
    }
    

    三、加载 BeanDefinition

    源代码【AbstractXmlApplicationContext】

    @Override
    protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException {
        // 1. 创建 XmlBeanDefinitionReader
        XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);
    
        // 2. 对 beanDefinitionReader 进行环境变量的设置
        beanDefinitionReader.setEnvironment(this.getEnvironment());
        beanDefinitionReader.setResourceLoader(this);
        beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this));
    
        // 3. 对 beanDefinitionReader 进行设置,默认可以覆盖
        initBeanDefinitionReader(beanDefinitionReader);
        loadBeanDefinitions(beanDefinitionReader);
    }
    
    protected void initBeanDefinitionReader(XmlBeanDefinitionReader reader) {
        reader.setValidating(this.validating);
    }
    

    在初始化了 DefaultListableBeanfactory 和 XmlBeanDefinitionReader,后就可以进行配置文件的读取了。

    protected void loadBeanDefinitions(XmlBeanDefinitionReader reader) 
            throws BeansException, IOException {
        Resource[] configResources = getConfigResources();
        if (configResources != null) {
            reader.loadBeanDefinitions(configResources);
        }
        String[] configLocations = getConfigLocations();
        if (configLocations != null) {
            reader.loadBeanDefinitions(configLocations);
        }
    }
    

    使用 XmlBeanDefinitionReader 的 loadBeanDefinitions 方法进行配置文件的加载机注册相信大家已经不陌生,这完全就是开始 BeanFactory 的套路。因为在 XmlBeanDefinitionReader 中已经将之前初始化的 DefaultlistableBeanfactory 注册进去了,所以 XmlBeanDefinitionReader 所读取的 BeanDefinitionHolder 都会注册到 DefaultListableBeanfactory 中。

    此时的 BeanFactory 已经解析了所有的 BeanDefinition,可以进行 bean 的加载了,不过在加载前 Spring 还做了一些其它的工作。


    每天用心记录一点点。内容也许不重要,但习惯很重要!

  • 相关阅读:
    绕过验证码登陆的方法(适合只需登陆一次可以记住登陆台的网站)
    Throughput Controller(吞吐量控制器) 感觉就像个线程控制器来的
    时间戳 和 日期 转换的方法 (含获取当前时间戳的方法)
    pip使用笔记
    可以模拟多种浏览器的网站
    浏览器兼容性说明
    测试套件的使用
    python 时间对比大小 和 间隔多少天
    django数据库操作
    mysql连接工具记录
  • 原文地址:https://www.cnblogs.com/binarylei/p/10423528.html
Copyright © 2011-2022 走看看