HttpServletBean
当用户第一次请求的时候会调用,且只会调用一次
- HttpServletBean.init()
- FrameworkServlet.initServletBean()
- FrameworkServlet.initWebApplicationContext
调用链
- HttpServletBean.init()
- FrameworkServlet.initServletBean()
- FrameworkServlet.initWebApplicationContext()
protected WebApplicationContext initWebApplicationContext() {
// 获取根的Context对象,
// 比如说我用了Springboot或者注解的方式进行初始化,那么这里的Context就是Spring boot或者其他的context对象
WebApplicationContext rootContext =
WebApplicationContextUtils.getWebApplicationContext(getServletContext());
WebApplicationContext wac = null;
// 如果 context 不为空
// 这里的 webApplicationContext 是我们在创建 DispatcherServlet(applicationContext)的时候 设置进来的
if (this.webApplicationContext != null) {
wac = this.webApplicationContext;
// 如果 context 是 ConfigurableWebApplicationContext
if (wac instanceof ConfigurableWebApplicationContext) {
ConfigurableWebApplicationContext cwac = (ConfigurableWebApplicationContext) wac;
// 如果 ConfigurableWebApplicationContext 不是存活状态
// 这个值由我们设置由 我们传递的 webApplicationContext 在调用刷新的时候 会修改掉
// 换而言之就是 我们可以不调用 applicationContext.refresh(); 这个方法的话就会进入这个判断
if (!cwac.isActive()) {
// The context has not yet been refreshed -> provide services such as
// setting the parent context, setting the application context id, etc
// 父 上下文 ==null
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);
}
// 这里会去 调用 refresh() 方法..也就是说 refresh 方法可能在用户第一访问的时候才去刷新...
configureAndRefreshWebApplicationContext(cwac);
}
}
}
// 如果为空,也就说我们在创建 DispatcherServlet()的时候 没有传递 applicationContext 则会进入 这个判断
if (wac == null) {
// 查看是否有已在servlet上下文中注册。 如果有一个存在,就假定它存在父上下文(如果有)已经设置,并且用户已执行任何初始化,如:设置上下文id
// 会根据 contextAttribute 去查找 WebApplicationContext
wac = findWebApplicationContext();
}
//如果没有找到那么就通过rootContext 去创建一个Context对象
if (wac == null) {
// 需要注意的是这里去创建的是 XmlWebApplicationContext
// 需要 /WEB-INF/app-servlet.xml 因为去加载 Bean 的是会读取这个 文件...
// 而由于我使用的注解类型所以不适用自动创建...
wac = createWebApplicationContext(rootContext);
}
// 判断 是否刷新过
if (!this.refreshEventReceived) {
//上下文不是具有refreshsupport的ConfigurableApplicationContext,或者在构造时注入的上下文已经被刷新->在此处手动触发初始onRefresh。
synchronized (this.onRefreshMonitor) {
onRefresh(wac);
}
}
//如果允许公开Context的话那么就把spring context放入到spring的ServletContext中
// 这样我们就可以通过 Servlet域 获取到 这个 WebApplicationContext
if (this.publishContext) {
// Publish the context as a servlet context attribute.
String attrName = getServletContextAttributeName();
getServletContext().setAttribute(attrName, wac);
}
return wac;
}
onRefresh
这个方法比较重要…
FrameworkServlet.onRefresh() 定义的空实现,由DispatcherServlet.onRefresh() 覆盖了.所以这里调用的是 DispatcherServlet.onRefresh()
protected void onRefresh(ApplicationContext context) {
initStrategies(context);
}
initStrategies
DispatcherServlet.initStrategies()
就是初始化一些对象,当然如果从 容器中获取到就不会进行初始化,如果没有获取到才会创建一个默认的
DispatcherServlet.properties
默认的文件 ,会从这个文件读出来…然后创建默认值
protected void initStrategies(ApplicationContext context) {
// 初始化 MultipartResolver 如果没有 则会设置一个 null
// 用于处理文件上传
initMultipartResolver(context);
// 初始化 LocaleResolver 如果没有 则会创建一个默认的
initLocaleResolver(context);
// 初始化 ThemeResolver 如果没有 则会创建一个默认的
initThemeResolver(context);
// 初始化 HadnlerMappings
initHandlerMappings(context);
// 初始化 HandlerAdapters
initHandlerAdapters(context);
// 初始化 HandlerExceptionResolvers
initHandlerExceptionResolvers(context);
// 初始化 RequestToViewNameTranslator
initRequestToViewNameTranslator(context);
// 初始化 ViewResolvers
initViewResolvers(context);
// 初始化 FlashMapManager
initFlashMapManager(context);
}
后言
剩下的initStrategies
参考后续文章… 会一个章节章节的分析里面的代码
本来想一起 分析的.但是合在一起 太长太长了.如果每个点都讲清楚… 太乱太乱了…