Spring - IoC 源码阅读笔记:AbstractApplicationContext - obtainFreshBeanFactory()

in TCEHJava with 0 comment

obtainFreshBeanFactory() 方法

    protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
        // 抽象方法,由子类来实现
        refreshBeanFactory();
        // 抽象方法,由子类来实现。返回上一步创建的 BeanFactory
        return getBeanFactory();
    }
    protected abstract void refreshBeanFactory() throws BeansException, IllegalStateException;
    public abstract ConfigurableListableBeanFactory getBeanFactory() throws IllegalStateException;

分为两种情况:

一、继承自AbstractRefreshableApplicationContext抽象类

refreshBeanFactory() 方法会关闭原有 BeanFactory ,再创建新的 BeanFactory ,并解析所有 Spring 配置文件(通常我们会放在 resources 目录下),将所有 Spring 配置文件中的 bean 定义封装成 BeanDefinition,加载到 BeanFactory 中。如果解析到 注解时,会扫描 base-package 指定的目录,将该目录下使用指定注解(@Controller、@Service、@Component、@Repository)的 bean 定义也同样封装成 BeanDefinition,加载到 BeanFactory 中。

上面提到的 “加载到 BeanFactory 中” 的内容主要指的是添加到以下3个缓存:

    @Override
    protected final void refreshBeanFactory() throws BeansException {
        // 存在 BeanFactory ,则销毁 Beans ,关闭 BeanFactory 
        if (hasBeanFactory()) {
            destroyBeans();
            closeBeanFactory();
        }
        try {
            // 创建 BeanFactory
            DefaultListableBeanFactory beanFactory = createBeanFactory();
            beanFactory.setSerializationId(getId());
            // 自定义配置
            customizeBeanFactory(beanFactory);
            // 从 XML 配置文件或 Properties 配置文件或注解中加载 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);
        }
    }

    // 从 XML 配置中加载 Bean 定义。由于目前 SpringBoot 是主流,这里就不深入研究啦。
    protected abstract void loadBeanDefinitions(DefaultListableBeanFactory beanFactory)
            throws BeansException, IOException;

    // 可以在子类中重写该方法,进行自定义配置
    protected void customizeBeanFactory(DefaultListableBeanFactory beanFactory) {
        // 是否允许覆盖同名称的不同定义的对象
        if (this.allowBeanDefinitionOverriding != null) {
            beanFactory.setAllowBeanDefinitionOverriding(this.allowBeanDefinitionOverriding);
        }
        // 是否允许bean之间存在循环依赖
        if (this.allowCircularReferences != null) {
            beanFactory.setAllowCircularReferences(this.allowCircularReferences);
        }
    }

二、继承自GenericApplicationContext类

refreshBeanFactory() 方法仅为 BeanFactory 属性 serializationId 赋值。因为已经拥有一个内部 BeanFactory 子类可以通过公共方法来注册bean。SpringBoot Web 使用的 IoC 实现类为 AnnotationConfigServletWebServerApplicationContext ,该类间接继承了 GenericApplicationContext 。

    @Override
    protected final void refreshBeanFactory() throws IllegalStateException {
        if (!this.refreshed.compareAndSet(false, true)) {
            throw new IllegalStateException(
                    "GenericApplicationContext does not support multiple refresh attempts: just call 'refresh' once");
        }
        this.beanFactory.setSerializationId(getId());
    }