概述
在开始之前我希望你能边操作边参考我的博客!!!
Servlet3.0
在说SpringMVC前先简单说一下Servlet3.0相关知识。Servlet3.0后项目里web.xml可以没有,原因是Servlet3.0后允许我们在
META-INF里键一个services包,在这个包中加入名为 javax.servlet.ServletContainerInitializer 的文件,内容为自定义类的全类名。
如SpringMVC中这样定义:
这个自定义类必须实现 ServletContainerInitializer 这个类,这个类只有一个方法:
void onStartup(Set<Class<?>> var1, ServletContext var2) throws ServletException;
可以理解为在服务器启动时会执行这个方法,这样我们就可以在这个方法里干活了。
如SpringMVC这样做:
SpringMVC容器启动过程分析
了解了Servlet3.0后我们在
SpringServletContainerInitializer 类的 ---> onStartup 方法 打上断点调试。
发现它只是执行了一遍这个方法什么也没干就返回了,因为我们并没有写一个配置类并实现
WebApplicationInitializer这个接口,因此我们先跳过这个类,从基本的web.xml配置的方式开始!!!
----------
在web.xml中配置DispatcherServlet和相关配置
DispatcherServlet的关系结构图
由于配置了<load-on-startup/>,所以当服务器启动时会加载DispatcherServlet.
Servlet生命周期要求,每个Servlet在第一次加载时都会调用其 init() 方法,但是DispatcherServlet本身没有这个方法,所以系统会去它父类HttpServletBean寻找,然后执行,以下是 init() 方法原码:
具体过程分析:
最后调用FrameworkServlet的 initServletBean()方法,FrameworkServlet就是用来初始化Spring容器的其原码如下:
接下来我们来看看 initWebApplicationContext() :
protected WebApplicationContext initWebApplicationContext() {
//通过WebApplicationContextUtils 获取Spring父容器
WebApplicationContext rootContext =
WebApplicationContextUtils.getWebApplicationContext(getServletContext());
//初始化一个SpringMVC的空容器
WebApplicationContext wac = null;
//判断是否已经有编程式的容器了 如果有最后调用configureAndRefreshWebApplicationContext(cwac)进行整合
//我们这里是没有
if (this.webApplicationContext != null) {
// A context instance was injected at construction time -> use it
wac = this.webApplicationContext;
if (wac instanceof ConfigurableWebApplicationContext) {
ConfigurableWebApplicationContext cwac = (ConfigurableWebApplicationContext) wac;
if (!cwac.isActive()) {
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);
}
}
}
//刚开始是Null所以进入
if (wac == null) {
//在servletContext中寻找 SpringMVC容器 刚开始是没有的
wac = findWebApplicationContext();
}
//进入
if (wac == null) {
// No context instance is defined for this servlet -> create a local one
//既没有编程式的容器也没有在servletContext中找到 所以 这里才是真正的创建springmvc容器实例
wac = createWebApplicationContext(rootContext);
}
if (!this.refreshEventReceived) {
//这里才是我们要的 真正初始化DispatcherServlet的时候
//这里我们会最后讲,因为这是容器初始化完后才执行的
//这个方法被DispatcherServlet覆写了
onRefresh(wac);
}
//最后将创建好的SpringMVC容器放入servletContext中
if (this.publishContext) {
// Publish the context as a servlet context attribute.
String attrName = getServletContextAttributeName();
getServletContext().setAttribute(attrName, wac);
if (this.logger.isDebugEnabled()) {
this.logger.debug("Published WebApplicationContext of servlet '" + getServletName() +
"' as ServletContext attribute with name [" + attrName + "]");
}
}
//将这个SpringMVC容器返回
return wac;
}
我们再来看一下:createWebApplicationContext()
最后我们看一下前面没有讲的 onRefresh(wac); 而这个方法被DispatcherServlet覆写了 容器初始化完后执行
这个方法是完成DispatcherServlet组装的核心方法:
它又调用initStrategies方法,我们看看它的原码:
不知道有没有种很亲切的感觉,哈哈... 它就是用来装配DispatcherServlet的部件的,DispatcherServlet的功能基本在这,我们打上断点,后续在深入。
最后我们总结一下:
Servlet3.0后项目里web.xml可以没有,原因是Servlet3.0后允许我们在META-INF里建一个services包,在这个包中加入名为 javax.servlet.ServletContainerInitializer 的文件,内容为自定义类的全类名。这也是基于JavaConfig配置Spring的基础。
接下来我们对SpringMVC容器和DispatcherServlet的装配流程进行了分析
1)在web.xml中配置
2)调用HttpServletBean 的init方法,拿到初始化参数为DispatcherServlet赋值,并调用FrameworkServlet的 initServletBean()方法
3)接下来调用 initWebApplicationContext() 完成容器的创建
4)创建完容器后刷新容器onRefresh(wac),将DispatcherServlet与容器关联
5)调用initStrategies方法组装DispatcherServlet
总的流程就是四个init打头的方法init initServletBean initWebApplicationContext initStrategies
最后:因为这是一次新的开始,所以参考了牛人的博客加入了自己的理解和分析:https://blog.csdn.net/cwl_0514/article/details/80095880
最后
以上就是开朗小懒猪为你收集整理的Spring原码解析之SpringMVC(DispatcherServlet)初始化流程的全部内容,希望文章能够帮你解决Spring原码解析之SpringMVC(DispatcherServlet)初始化流程所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复