FrameworkServlet是spring mvc下一个setvlet的基类,它继承了HttpServletBean,HttpServletBean又继承了HttpServlet。 通过 HttpServletBean 源码解析中我们了解到HttpServletBean重写了servlet的init()方法,在init()方法中调用了initServletBean(), initServletBean()是个空方法需要子类去实现它。
FrameworkServlet做了一些什么事?
实现HttpServletBean中的initServletBean(),在initServletBean()创建或者刷新WebApplicationCentext容器
protectedfinalvoidinitServletBean()throwsServletException{this.getServletContext().log("InitializingSpring"+this.getClass().getSimpleName()+"'"+this.getServletName()+"'");if(this.logger.isInfoEnabled()){this.logger.info("InitializingServlet'"+this.getServletName()+"'");}longstartTime=System.currentTimeMillis();try{//初始化或者刷新WebApplicationContext容器this.webApplicationContext=this.initWebApplicationContext();this.initFrameworkServlet();}catch(RuntimeException|ServletExceptionvar4){this.logger.error("Contextinitializationfailed",var4);throwvar4;}if(this.logger.isDebugEnabled()){Stringvalue=this.enableLoggingRequestDetails?"shownwhichmayleadtounsafeloggingofpotentiallysensitivedata":"maskedtopreventunsafeloggingofpotentiallysensitivedata";this.logger.debug("enableLoggingRequestDetails='"+this.enableLoggingRequestDetails+"':requestparametersandheaderswillbe"+value);}if(this.logger.isInfoEnabled()){this.logger.info("Completedinitializationin"+(System.currentTimeMillis()-startTime)+"ms");}}
protectedWebApplicationContextinitWebApplicationContext(){WebApplicationContextrootContext=WebApplicationContextUtils.getWebApplicationContext(this.getServletContext());WebApplicationContextwac=null;if(this.webApplicationContext!=null){//实例在构造函数中被注入wac=this.webApplicationContext;if(wacinstanceofConfigurableWebApplicationContext){ConfigurableWebApplicationContextcwac=(ConfigurableWebApplicationContext)wac;//当前容器为不可用状态下if(!cwac.isActive()){//父容器是否存在不存在则设置父容器if(cwac.getParent()==null){cwac.setParent(rootContext);}//这个方法可以刷新WebApplicationContext中配置,this.configureAndRefreshWebApplicationContext(cwac);}}}if(wac==null){//从ContextAttribute中查找WebApplicationContextwac=this.findWebApplicationContext();}if(wac==null){//如果还是没有找到则会去创建一个WebApplicationContextwac=this.createWebApplicationContext(rootContext);}if(!this.refreshEventReceived){//刷新WebApplicationContext配置,onRefresh需要子类去实现synchronized(this.onRefreshMononRefresh需要子类去实现itor){this.onRefresh(wac);}}if(this.publishContext){//将当前容器保存到ServletContext中StringattrName=this.getServletContextAttributeName();this.getServletContext().setAttribute(attrName,wac);}returnwac;}
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 方法