一,Spring启动流程概述
Spring的IoC容器在实现控制反转和依赖注入的过程中,可以划分为两个阶段:
-
容器启动阶段
-
Bean实例化阶段
容器初始化
-
加载配置
-
分析配置信息
-
将Bean信息装配到BeanDefinition
-
将Bean信息注册到相应的BeanDefinitionRegistry
-
其他后续处理
容器实例化
-
根据策略实例化对象
-
装配依赖
-
Bean初始化前处理
-
对象初始化
-
对象其他处理
-
注册回调接口
二,Spring启动流程详解
Spring启动流程源码概览
ClassPathXmlApplicationContext
public ClassPathXmlApplicationContext(String[] configLocations, boolean refresh, ApplicationContext parent)
throws BeansException {
super(parent);
setConfigLocations(configLocations);
if (refresh) {
refresh();
}
}
public ClassPathXmlApplicationContext(String[] paths, Class<?> clazz, ApplicationContext parent)
throws BeansException {
super(parent);
Assert.notNull(paths, "Path array must not be null");
Assert.notNull(clazz, "Class argument must not be null");
this.configResources = new Resource[paths.length];
for (int i = 0; i < paths.length; i++) {
this.configResources[i] = new ClassPathResource(paths[i], clazz);
}
refresh();
}
AbstractApplicationContext
public void refresh() throws BeansException, IllegalStateException {
// 方法加锁避免多线程同时刷新Spring上下文
synchronized (this.startupShutdownMonitor) {
// 准备上下文刷新
prepareRefresh();
// 告诉子类刷新内部的beanFactory返回新的BeanFactory
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// 在当前上下文中准备要beanFactory
prepareBeanFactory(beanFactory);
try {
// 允许在上下文子类中对beanFactory进行后置处理
postProcessBeanFactory(beanFactory);
// 在上下文中将BeanFactory处理器注册为Bean
invokeBeanFactoryPostProcessors(beanFactory);
// 注册Bean处理器用于拦截Bean的创建
registerBeanPostProcessors(beanFactory);
// 在上下文中初始化国际化信息
initMessageSource();
// 在上下文中初始化event multicaster(事件多播器)
initApplicationEventMulticaster();
// 在指定的上下文子类中初始化其他指定的beans
onRefresh();
// 检查并注册事件监听
registerListeners();
// 实例化所有剩余的(非延迟初始化)单例
finishBeanFactoryInitialization(beanFactory);
// 最后一步:发布相应的事件
finishRefresh();
}
catch (BeansException ex) {
if (logger.isWarnEnabled()) {
logger.warn("Exception encountered during context initialization - " +
"cancelling refresh attempt: " + ex);
}
// 如果出现异常则销毁已创建的单例
destroyBeans();
// 重置活动标志。
cancelRefresh(ex);
// 将异常传递给调用者
throw ex;
}
finally {
// Reset common introspection caches in Spring's core, since we
// might not ever need metadata for singleton beans anymore...
resetCommonCaches();
}
}
}
整个refresh()的代码都是同步的,而对应的同步对象是startupShutdownMonitor。startupShutdownMonitor只在refresh()和close()两个方法里被用到,而它是用来同步applicationContext的刷新和销毁。
第一步 刷新准备
protected void prepareRefresh() {
// 设置启动时间。当前毫秒数代表当前applicationContext的创建时间
this.startupDate = System.currentTimeMillis();
// 设置容器关闭标志
this.closed.set(false);
// 设置启动标志
this.active.set(true);
if (logger.isInfoEnabled()) {
logger.info("Refreshing " + this);
}
// 初始化属性资源
initPropertySources();
// 验证所有的属性是否都是可解析的
getEnvironment().validateRequiredProperties();
// ApplicationEvent初始化
this.earlyApplicationEvents = new LinkedHashSet<ApplicationEvent>();
}