HttpServletBean的init()核心代码:
public final void init() throws ServletException {
// Set bean properties from init parameters.
// Servlet初始化参数,如:contextAttribute,contextClass,contextConfigLocation,namespace设置到该组件上
try {
PropertyValues pvs = new ServletConfigPropertyValues(getServletConfig(), this.requiredProperties);
BeanWrapper bw = PropertyAccessorFactory.forBeanPropertyAccess(this);
ResourceLoader resourceLoader = new ServletContextResourceLoader(getServletContext());
bw.registerCustomEditor(Resource.class, new ResourceEditor(resourceLoader, getEnvironment()));
initBeanWrapper(bw);
bw.setPropertyValues(pvs, true);
}
// 省略异常判断代码
initServletBean(); // FrameworkServlet覆盖实现的方法
// 省略日志输出代码
}
SpringIoC容器启动时,会执行HttpServletBean继承HttpServlet的init()方法,初始化contextAttribute,contextClass,contextConfigLocation,namespace到该组件上,通过BeanWrapper进行设置。并且由子类实现initServletBean()作为扩展点,该方法由FrameworkServlet覆盖。
FrameworkServlet的initServletBean()核心代码:
protected final void initServletBean() throws ServletException {
// 省略日志输出代码
try {
this.webApplicationContext = initWebApplicationContext(); // 初始化Web上下文
initFrameworkServlet(); // 子类覆盖实现的方法
}
// 省略异常判断和日志输出代码
}
initWebApplicationContext()的核心代码:
protected WebApplicationContext initWebApplicationContext() {
// ContextLoaderListener初始化的上下文, ContextLoaderListener的上下文对整个Spring都有效
WebApplicationContext rootContext = WebApplicationContextUtils.getWebApplicationContext(getServletContext());
WebApplicationContext wac = null;
// A context instance was injected at construction time -> use it
// 创建Servlet上下文
wac = this.webApplicationContext;
if (wac instanceof ConfigurableWebApplicationContext) {
ConfigurableWebApplicationContext cwac = (ConfigurableWebApplicationContext) wac;
if (!cwac.isActive()) {
// The context has not yet been refreshed -> provide services such as
// setting the parent context, setting the application context id, etc
if (cwac.getParent() == null) {
// The context instance was injected without an explicit parent -> set
// the root application context (if any; may be null) as the parent
cwac.setParent(rootContext);
}
configureAndRefreshWebApplicationContext(cwac);
}
}
}
if (wac == null) {
// No context instance was injected at construction time -> see if one
// has been registered in the servlet context. If one exists, it is assumed
// that the parent context (if any) has already been set and that the
// user has performed any initialization such as setting the context id
// 查找已绑定的上下文
wac = findWebApplicationContext();
}
if (wac == null) {
// No context instance is defined for this servlet -> create a local one
// 如果还是没有对应的上下文,就自己创建一个继承rootContext的上下文
wac = createWebApplicationContext(rootContext);
}
if (!this.refreshEventReceived) {
// Either the context is not a ConfigurableApplicationContext with refresh
// support or the context injected at construction time had already been
// refreshed -> trigger initial onRefresh manually here.
// 刷新上下文,初始化使用策略
onRefresh(wac); // DispatchServlet覆盖实现
}
if (this.publishContext) {
// Publish the context as a servlet context attribute.
String attrName = getServletContextAttributeName();
getServletContext().setAttribute(attrName, wac);
// 省略日志输出代码
}
return wac;
}
初始化SpringMVC上下文时,会首先查找ContextLoaderListener初始化的上下文,并创建继承自ContextLoaderListener上下文的child上下文,调用了onRefresh()方法初始化child上下文。
DispatchServlet的onRefresh()核心代码:
protected void onRefresh(ApplicationContext context) {
initStrategies(context);
}
protected void initStrategies(ApplicationContext context) {
initMultipartResolver(context); // 初始化上传文件解析器
initLocaleResolver(context); // 初始化国际化解析器
initThemeResolver(context); // 初始化主题解析器
initHandlerMappings(context); // 初始化处理器映射器
initHandlerAdapters(context); // 初始化处理器适配器
initHandlerExceptionResolvers(context); // 初始化处理器异常解析器
initRequestToViewNameTranslator(context); // 初始化请求至视图名称的解析器
initViewResolvers(context); // 初始化视图解析器
initFlashMapManager(context); // 初始化Flash映射管理器
}
至此,DispatchServlet初始化完毕,整个DispatchServlet初始化过程,主要执行了2件事:
1、初始化Spring Web MVC使用的Web上下文,并且可能指定父容器为(ContextLoaderListener加载了根上下文)。
2、初始化DispatcherServlet使用的策略,如HandlerMapping、HandlerAdapter等。
接下来,探讨DispatchServlet处理请求的流程。https://blog.csdn.net/Super_Me_Jason/article/details/79898731