在前文知道了,DispatcherServlet的init方法是springmvc项目初始化的入口,init方法内部又调用了initServletBean
protected final void initServletBean() throws ServletException {
//省略
try {
//初始化spring容器,在这里完成应用内bean的扫描和创建
this.webApplicationContext = initWebApplicationContext();
//初始化servlet,默认空实现,由子类实现
initFrameworkServlet();
}
catch (ServletException | RuntimeException ex) {
logger.error("Context initialization failed", ex);
throw ex;
}
}
//省略
protected WebApplicationContext initWebApplicationContext() {
WebApplicationContext rootContext =
WebApplicationContextUtils.getWebApplicationContext(getServletContext());
WebApplicationContext wac = null;
if (this.webApplicationContext != null) {
wac = this.webApplicationContext;
if (wac instanceof ConfigurableWebApplicationContext) {
ConfigurableWebApplicationContext cwac = (ConfigurableWebApplicationContext) wac;
if (!cwac.isActive()) {
if (cwac.getParent() == null) {
cwac.setParent(rootContext);
}
//核心方法
configureAndRefreshWebApplicationContext(cwac);
}
}
}
//省略.....
if (this.publishContext) {
// Publish the context as a servlet context attribute.
String attrName = getServletContextAttributeName();
getServletContext().setAttribute(attrName, wac);
}
return wac;
}
configureAndRefreshWebApplicationContext方法主要就是初始化context的一些成员属性,将servlet信息加入到spring容器,然后刷新容器
protected void configureAndRefreshWebApplicationContext(ConfigurableWebApplicationContext wac) {
//省略.....
//设置servletContext和servletConfig,这样在容器就可以使用这两个对象了
wac.setServletContext(getServletContext());
wac.setServletConfig(getServletConfig());
wac.setNamespace(getNamespace());
//添加监听器,当spring容器完成创建并刷新时,会回调此观察者,
//这里很重要,因为DispatcherServlet的几个重要组件都是在回调方法里面进行处理和赋值的
wac.addApplicationListener(new SourceFilteringListener(wac, new ContextRefreshListener()));
//设置环境的propertyResource
ConfigurableEnvironment env = wac.getEnvironment();
if (env instanceof ConfigurableWebEnvironment) {
((ConfigurableWebEnvironment) env).initPropertySources(getServletContext(), getServletConfig());
}
//空实现,留给子类处理
postProcessWebApplicationContext(wac);
//调用初始化器,在刷新容器之前,做一些初始化操作
applyInitializers(wac);
//刷新容器,这里对刷新容器就不展开了,这个主要是spring的基础知识
wac.refresh();
}
当完成spring容器的刷新之后,ContextRefreshListener的回调方法便会收到通知
public void onApplicationEvent(ContextRefreshedEvent event) {
FrameworkServlet.this.onApplicationEvent(event);
}
通过跟进FrameworkServlet的onApplicationEvent方法,可以看到springmvc几个重要组件的初始化
protected void initStrategies(ApplicationContext context) {
initMultipartResolver(context);
initLocaleResolver(context);
initThemeResolver(context);
initHandlerMappings(context);
initHandlerAdapters(context);
initHandlerExceptionResolvers(context);
initRequestToViewNameTranslator(context);
initViewResolvers(context);
initFlashMapManager(context);
}
整个springmvc的核心就是上述几个组件,这个后面再展开。当spring容器完成刷新并通知了观察者后,程序流程又回到了initWebApplicationContext
if (this.publishContext) {
//将容器上下文对象添加到ServletContext中
String attrName = getServletContextAttributeName();
getServletContext().setAttribute(attrName, wac);
}
至此,springmvc的初始化流程就走完了,也就是DispatcherServlet的init方法执行完毕。web应用启动了