1. 程式人生 > >ApplicationContext(三)BeanFactory 初始化

ApplicationContext(三)BeanFactory 初始化

allow text ring 它的 gre 定制 throws cee 記錄

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 還做了一些其它的工作。


每天用心記錄一點點。內容也許不重要,但習慣很重要!

ApplicationContext(三)BeanFactory 初始化