Spring源码解析-容器的功能扩展

Scroll Down

概述

Spring中还提供了另一个接口ApplicationContext,用于扩展BeanFactory中现有的功能。

扩展功能

public void refresh() throws BeansException, IllegalStateException {
    synchronized (this.startupShutdownMonitor) {
        // Prepare this context for refreshing.
        prepareRefresh();

        // Tell the subclass to refresh the internal bean factory.
        ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

        // Prepare the bean factory for use in this context.
        prepareBeanFactory(beanFactory);

        try {
            // Allows post-processing of the bean factory in context subclasses.
            postProcessBeanFactory(beanFactory);

            // Invoke factory processors registered as beans in the context.
            invokeBeanFactoryPostProcessors(beanFactory);

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

            // Initialize message source for this context.
            initMessageSource();

            // Initialize event multicaster for this context.
            initApplicationEventMulticaster();

            // Initialize other special beans in specific context subclasses.
            onRefresh();

            // Check for listener beans and register them.
            registerListeners();

            // Instantiate all remaining (non-lazy-init) singletons.
            finishBeanFactoryInitialization(beanFactory);

            // Last step: publish corresponding event.
            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();
        }
    }
}

下面概括下ClassPathXmlApplicationContext初始化的步骤。
1、初始化前的准备工作,例如对系统属性或者环境变量进行准备及验证。
2、初始化BeanFactory,并进行XML文件读取。
3、对BeanFactory进行各种功能填充。
4、子类覆盖方法做额外的处理。
5、激活各种BeanFactory处理器。
6、注册拦截bean创建的bean处理器,这里只是注册,真正的调用是在getBean时候。
7、为上下文初始化Message源,即对不同语言的消息体进行国际化处理。
8、初始化应用消息广播器。
9、留给子类来初始化其他的bean。
10、在所有注册的bean中查找listener bean,注册到消息广播器中。
11、初始化剩下的单实例(非惰性的)。
12、完成刷新过程,通知生命周期处理器lifecycleProcessor刷新过程,同时发出ContextRefreshEvent通知别人。

环境准备

加载BeanFactory

protected final void refreshBeanFactory() throws BeansException {
    if (hasBeanFactory()) {
        destroyBeans();
        closeBeanFactory();
    }
    try {
        // 创建DefaultListableBeanFactory
        DefaultListableBeanFactory beanFactory = createBeanFactory();
        beanFactory.setSerializationId(getId());
        customizeBeanFactory(beanFactory);
        loadBeanDefinitions(beanFactory);
        synchronized (this.beanFactoryMonitor) {
            this.beanFactory = beanFactory;
        }
    }
    catch (IOException ex) {
        throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
    }
}

我们详细分析上面的每个步骤。
1、创建DefaultListableBeanFactory。
2、指定序列化ID。
3、定制BeanFactory。
4、加载BeanDefinition。
5、使用全局变量记录BeanFactory类实现。