容器启动核心都是通过监听或某个方法来调用ApplicationContext.refresh()。
一、SSM
1、在 web.xml 配置监听器
<!-- spring监听器 -->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
2、容器启动时会调用 ContextLoaderListener 中的 contextInitialized 方法。
public class ContextLoaderListener extends ContextLoader implements ServletContextListener {
@Override
public void contextInitialized(ServletContextEvent event) {
initWebApplicationContext(event.getServletContext());
}
}
3、调用父类的 initWebApplicationContext 方法,在该方法中创建、启动上下文。
public class ContextLoader {
public WebApplicationContext initWebApplicationContext(ServletContext servletContext) {
try {
if (this.context == null) {
// 通过 createWebApplicationContext 方法创建上下文,默认创建 XmlWebApplicationContext
this.context = createWebApplicationContext(servletContext);
}
if (this.context instanceof ConfigurableWebApplicationContext) {
ConfigurableWebApplicationContext cwac = (ConfigurableWebApplicationContext) this.context;
if (!cwac.isActive()) {
// 在该方法中调用上下文的 refresh 方法,refresh 就是启动上下文的入口
configureAndRefreshWebApplicationContext(cwac, servletContext);
}
}
}
}
protected void configureAndRefreshWebApplicationContext(ConfigurableWebApplicationContext wac, ServletContext sc) {
wac.refresh();
}
}
二、springboot
1、从启动类开始
2、找到 SpringApplication 中,最后重载的 run 方法
public ConfigurableApplicationContext run(String... args) {
...
ConfigurableApplicationContext context = null;
...
try {
...
// 通过 createApplicationContext 方法创建上下文,根据 Web 环境不同创建的上下文也不同
context = createApplicationContext();
...
// 该方法用于启动上下文
refreshContext(context);
...
}
catch (Throwable ex) {
...
}
context = createApplicationContext();
}
3、进入 refreshContext 方法,里面调用了 refresh 方法
4、这里最终也是调用 ApplicationContext 的 refresh 方法来启动上下文
三、rerfrsh()方法详解
注意注册postProcess和调用postProcess是不一样的概念!
AbstractApplicationContext
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
// 1. 初始化 refresh 的上下文环境,就是记录下容器的启动时间、标记已启动状态、处理配置文件中的占位符
prepareRefresh();
// 2. 初始化 BeanFactory,加载并解析配置(xxApplicationContext.loadBeanDefinitions--xxBeanDefinitionReader.load)
ConfigurableListableBeanFactory beanFactory = this.obtainFreshBeanFactory();
/* ---至此,已经完成了简单容器的所有功能,下面开始对简单容器进行增强--- */
// 3. 对 BeanFactory 进行功能增强,如设置BeanFactory的类加载器,添加几个BeanPostProcessor,手动注册几个特殊的 bean
prepareBeanFactory(beanFactory);
try {
// 4. 后置处理 beanFactory,交由子类实现。注册BeanFactoryPostProcessor等
postProcessBeanFactory(beanFactory);
// 5. 调用已注册的 BeanFactoryPostProcessor
invokeBeanFactoryPostProcessors(beanFactory);
// 6. 注册 BeanPostProcessor,仅仅是注册,调用在getBean的时候
registerBeanPostProcessors(beanFactory);
// 7. 初始化MessageSource组件(做国际化功能;消息绑定,消息解析)
initMessageSource();
// 8. 初始化事件广播器
initApplicationEventMulticaster();
// 9. 留给子类实现的模板方法
onRefresh();
// 10. 注册事件监听器
registerListeners();
// 11. 实例化所有非延迟加载的单例(里面会调用已注册的BeanPostProcessor)
finishBeanFactoryInitialization(beanFactory);
// 12. 完成刷新过程,发布应用事件
finishRefresh();
} catch (BeansException ex) {
// 13.销毁已经初始化的 singleton 的 Beans,以免有些 bean 会一直占用资源
this.destroyBeans();
// Reset 'active' flag.
this.cancelRefresh(ex);
// Propagate exception to caller.
throw ex;
} finally {
this.resetCommonCaches();
}
}
}