高级容器ApplicationContext的初始过程---总览与概述

     作为Spring的IoC最为核心的部分便是“容器”的概念,它用来统一管理所有bean的定义以及bean之间可能的相互依赖关系。在Spring中,容器分为基础容器(BeanFactory)和高级容器(ApplicationContext),BeanFactory作为Spring最底层的核心实现,就像是Spring的根基,提供了Spring最基本的功能:bean的管理。而ApplicationContext则是对BeanFactory的扩展(继承自BeanFactory),提供了更为丰富的功能,如国际化资源访问,事件传播机制等,对于日常工作中开发的Spring企业应用和系统,都基本以ApplicationContext为基础,所以掌握ApplicationContext的原理和实现就显得尤为重要。下面就对ApplicationContext的底层实现做一个深入的了解。

    ApplicationContext作为高级容器接口,有很多常用的实现类,如FileSystemXmlApplicationContext和ClassPathXmlApplicationContext,它们都继承于AbstractXmlApplicationContext抽象类(ApplicationContext接口实现基础核心类)。首先我们以FileSystemXmlApplicationContext加载配置文件为例,看看该类是怎么一步一步完成初始化的:

 ApplicationContext ac=new FileSystemXmlApplicationContext("myApplicationContextTest.xml");
进入FileSystemXmlApplicationContext类,看一下构造过程:
public FileSystemXmlApplicationContext(String configLocation) throws BeansException {
        this(new String[] {configLocation}, true, null);
    }
    
public FileSystemXmlApplicationContext(String[] configLocations, boolean refresh, ApplicationContext parent)
            throws BeansException {
        super(parent);
        setConfigLocations(configLocations);//设置配置路径
        if (refresh) {
            refresh();//容器的初始化入口
        }
    }

跟踪setConfigLocations(configLocations)方法,进入到AbstractRefreshableConfigApplicationContext类中,实现方法如下:

public void setConfigLocations(String... locations) {
		if (locations != null) {
			Assert.noNullElements(locations, "Config locations must not be null");
			this.configLocations = new String[locations.length];
			for (int i = 0; i < locations.length; i++) {
			  this.configLocations[i] = resolvePath(locations[i]).trim();//解析给定的路径
			}
		}
		else {
			this.configLocations = null;
		}
 }

下面我们重点看一下refresh()方法的实现,该方法封装在了基础核心抽象类AbstractApplicationContext中:

@Override
public void refresh() throws BeansException, IllegalStateException {
	    synchronized (this.startupShutdownMonitor) { //锁机制,同一时间只能被单一访问
			//准备上下文环境的初始化,对系统属性和环境变量进行准备和验证
			prepareRefresh();

			// 初始化beanfactory,并进行XML文件读取
			ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

			//丰富beanfactory的功能,如增加类加载机制,SPEL表达式语言支持,后置处理器等等
			prepareBeanFactory(beanFactory);

			try {
				//子类覆盖方法,再进一步做一些其他工作,如注册系统上下文request/session属性以及和servlet相关的处理
				postProcessBeanFactory(beanFactory);

				// 激活各种beanfactory处理器
				invokeBeanFactoryPostProcessors(beanFactory);

				// 注册拦截bean所创建bean处理器
				registerBeanPostProcessors(beanFactory);

				// 初始化message消息源,支持多语言,实现国际化
				initMessageSource();

				// 初始化应用消息传播器
				initApplicationEventMulticaster();

				// 留给子类实现,完成其他的bean的初始化
				onRefresh();

				//检查bean监听器,并注册到消息广播器中
				registerListeners();

				// 初始化所有剩下的非惰性的单实例bean
				finishBeanFactoryInitialization(beanFactory);

				// 最后一步,完成刷新过程,通知生命周期处理器完成初始化
				finishRefresh();
			}

			catch (BeansException ex) {
				if (logger.isWarnEnabled()) {
					logger.warn("Exception encountered during context initialization - " +
							"cancelling refresh attempt: " + ex);
				}

				// 销毁已经创建单实例bean
				destroyBeans();

				//重置active标志
				cancelRefresh(ex);

				// Propagate exception to caller.
				throw ex;
			}

			finally {
				//重置公共缓存机制
				resetCommonCaches();
			}
		}
   }

从这里可以看出,高级容器ApplicationContext的初始化过程代码结构非常清晰明了,并没有我们想象中的那么难,“大而化小,逐渐细分,统筹工作”正是体现Spring乃至其他很多优秀开源软件的核心思想。下面沿着上述的初始化总体流程,继续深入下去,发现每一步所做的具体工作也并没有那么简单。






你可能感兴趣的:(Spring源码之旅)