FrameworkServlet是spring mvc下一个setvlet的基类,它继承了HttpServletBean,HttpServletBean又继承了HttpServlet
通过 HttpServletBean 源码解析中我们了解到HttpServletBean重写了servlet的init()方法,在init()方法中调用了initServletBean(), initServletBean()是个空方法需要子类去实现它
FrameworkServlet做了一些什么事?
- 实现HttpServletBean中的initServletBean(),在initServletBean()创建或者刷新WebApplicationCentext容器
protected final void initServletBean() throws ServletException {
this.getServletContext().log("Initializing Spring " + this.getClass().getSimpleName() + " '" + this.getServletName() + "'");
if (this.logger.isInfoEnabled()) {
this.logger.info("Initializing Servlet '" + this.getServletName() + "'");
}
long startTime = System.currentTimeMillis();
try {
//初始化或者刷新WebApplicationContext容器
this.webApplicationContext = this.initWebApplicationContext();
this.initFrameworkServlet();
} catch (RuntimeException | ServletException var4) {
this.logger.error("Context initialization failed", var4);
throw var4;
}
if (this.logger.isDebugEnabled()) {
String value = this.enableLoggingRequestDetails ? "shown which may lead to unsafe logging of potentially sensitive data" : "masked to prevent unsafe logging of potentially sensitive data";
this.logger.debug("enableLoggingRequestDetails='" + this.enableLoggingRequestDetails + "': request parameters and headers will be " + value);
}
if (this.logger.isInfoEnabled()) {
this.logger.info("Completed initialization in " + (System.currentTimeMillis() - startTime) + " ms");
}
}
protected WebApplicationContext initWebApplicationContext() {
WebApplicationContext rootContext = WebApplicationContextUtils.getWebApplicationContext(this.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);
}
//这个方法可以刷新WebApplicationContext中配置,
this.configureAndRefreshWebApplicationContext(cwac);
}
}
}
if (wac == null) {
//从ContextAttribute中查找WebApplicationContext
wac = this.findWebApplicationContext();
}
if (wac == null) {
//如果还是没有找到则会去创建一个WebApplicationContext
wac = this.createWebApplicationContext(rootContext);
}
if (!this.refreshEventReceived) {
//刷新WebApplicationContext配置,onRefresh需要子类去实现
synchronized(this.onRefreshMononRefresh需要子类去实现itor) {
this.onRefresh(wac);
}
}
if (this.publishContext) {
//将当前容器保存到ServletContext中
String attrName = this.getServletContextAttributeName();
this.getServletContext().setAttribute(attrName, wac);
}
return wac;
}
WebApplicationContext寻找以及创建包含以下几个步骤
- this.webApplicationContext不等于null,则判断当前webApplicationContext容器是否可用,不可用的情况下,判断是否设置了父容器,最后调用this.configureAndRefreshWebApplicationContext(cwac)刷新webApplicationContext配置
- webApplicationContext为空,则通过从web.xml配置中servlet参数查到对应的WebApplicationContext
- 如果依旧没有找到则创建webApplicationContext
configureAndRefreshWebApplicationContext
不管是单纯创建还是通过构造器注入,最终都会调用到configureAndRefreshWebApplicationContext()方法,configureAndRefreshWebApplicationContext()中调用了AbstractApplicationContext.refresh()刷新上下文环境,
AbstractApplicationContext.refresh()在最后一步调用finishRefresh()发布了ContextRefreshedEvent事件,则调用事件,从而FrameworkServlet监听到了ContextRefreshedEvent事件,则调用onRefresh()方法。
onRefresh()最后被DispatcherServlet所实现,初始化了它的九大组件
总结
- HttpServletBean 覆盖 GenericServlet 的 init() 方法,该方法调用 initServletBean() 方法,该方法被 FrameworkServlet 覆盖
- 在 FrameworkServlet 的 initServletBean() 方法中,它调用 initWebApplicationContext() 方法
- 在该方法中,它检查 webApplicationContext 是否是 ConfigurableWebApplicationContext 的实例
- 如果是,则调用 configureAndRefreshWebApplicationContext() 方法
- 因为它在 webApplicationContext 上调用 refresh 方法
- 查看 AbstractApplicationContext 中 refresh() 方法的实现,最后调用了 finishRefresh() 方法
- 在该方法中它发布 ContextRefreshedEvent
- 在 FrameworkServlet 中有实现 ApplicationListener 的私有类 ContextRefreshListener
- 此类上的 onApplicationEvent() 方法调用 FrameworkServlet 的 onApplicationEvent() 方法
- 在该方法中,它调用由 DispatcherServlet 覆盖的 onRefresh 方法