首页 技术 正文
技术 2022年11月14日
0 收藏 668 点赞 2,849 浏览 3803 个字

了解一个项目启动如何实现是了解一个框架底层实现的一个必不可少的环节。从使用步骤来看,我们一般是引入包之后,配置web.xml文件。官方文档示例的配置如下:

<web-app>
<servlet>
<servlet-name>example</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet> <servlet-mapping>
<servlet-name>example</servlet-name>
<url-pattern>/example/*</url-pattern>
</servlet-mapping></web-app>

其实就是把请求引到DispatcherServlet类中去执行。而DispatcherServlet类其实是一个Servlet类的子类,他的继承结构如下:

SpringMvc 启动原理源码分析

我们都知道当项目启动时,servlet会执行init方法,在HttpServletBean中覆写了这个init方法。代码如下

@Override    
public final void init() throws ServletException {

if (logger.isDebugEnabled()) {
logger.debug("Initializing servlet '" + getServletName() + "'");
} // Set bean properties from init parameters.
try {
        //获取servletConfig
PropertyValues pvs = new ServletConfigPropertyValues(getServletConfig(), this.requiredProperties);
        //将dispatcherServlet对象封装到BeanWrapper类里
BeanWrapper bw = PropertyAccessorFactory.forBeanPropertyAccess(this);
        //获取servletContext
ResourceLoader resourceLoader = new ServletContextResourceLoader(getServletContext());
bw.registerCustomEditor(Resource.class, new ResourceEditor(resourceLoader, getEnvironment()));
        //空的方法
initBeanWrapper(bw);
bw.setPropertyValues(pvs, true);
}
catch (BeansException ex) {
logger.error("Failed to set bean properties on servlet '" + getServletName() + "'", ex);
throw ex;
} // Let subclasses do whatever initialization they like.
     //这个方法由FrameworkServlet提供实现
initServletBean(); if (logger.isDebugEnabled()) {
logger.debug("Servlet '" + getServletName() + "' configured successfully");
}
}

initServletBean();方法由FrameworkServlet类来实现的,而这个方法是初始化SpringMvc的上下文环境。从启动的打印日志我们来分析:(这里读取了springmvc.xml还解析了匹配到的类和方法)

信息: Loading XML bean definitions from class path resource [springmvc.xml]
三月 26, 2018 11:19:38 上午 org.springframework.web.servlet.handler.AbstractUrlHandlerMapping registerHandler
信息: Mapped URL path [/**] onto handler 'org.springframework.web.servlet.resource.DefaultServletHttpRequestHandler#0'
三月 26, 2018 11:19:38 上午 org.springframework.web.servlet.handler.AbstractHandlerMethodMapping registerHandlerMethod
信息: Mapped "{[/testExcel],methods=[],params=[],headers=[],consumes=[],produces=[],custom=[]}" onto public org.springframework.web.servlet.ModelAndView com.mmc.excel.TestExcelView.testExcel() throws java.io.UnsupportedEncodingException
三月 26, 2018 11:19:38 上午 org.springframework.web.servlet.handler.AbstractHandlerMethodMapping registerHandlerMethod
信息: Mapped "{[/myHandleMethod],methods=[],params=[],headers=[],consumes=[],produces=[],custom=[]}" onto public java.lang.String com.mmc.hanlemethod.TestHandleMethod.myHandleMethod(org.springframework.web.context.request.WebRequest,org.springframework.ui.Model)
三月 26, 2018 11:19:38 上午 org.springframework.web.servlet.handler.AbstractHandlerMethodMapping registerHandlerMethod
信息: Mapped "{[/pets/{petId}],methods=[GET],params=[],headers=[],consumes=[],produces=[],custom=[]}" onto public void com.mmc.helloworld.HelloMatrixVariable.findPet2(java.lang.String,int)
三月 26, 2018 11:19:38 上午 org.springframework.web.servlet.handler.AbstractHandlerMethodMapping registerHandlerMethod

HttpServletBean类的init方法内执行到initServletBean方法,这个方法被FrameworkServlet类覆写。这个方法里其实就一个有效的方法,即initWebApplicationContext();方法。这个方法会调用DispatcherServlet中的onRefresh()方法。然后会执行下面一段内容:

protected void initStrategies(ApplicationContext context) {
     //初始化上传文件解析器
initMultipartResolver(context);
     //初始化本地解析器
initLocaleResolver(context);
     //主题处理器
initThemeResolver(context);
     //映射处理器
initHandlerMappings(context);
     //处理适配器
initHandlerAdapters(context);
     //异常处理器
initHandlerExceptionResolvers(context);
     //请求到视图名的翻译器
initRequestToViewNameTranslator(context);
     //视图解析器
initViewResolvers(context);
     //初始化FlashManager
initFlashMapManager(context);
}

我理解的简单流程:servlet机制先会去获取web.xml配置文件,获取到servletConfig和servletContext,(关于servletConfig和context的博文)然后创建webApplicationContext,读取springmvc.xml,然后初始化适配器,解析器等。

另外还有一篇博文是讲SpringMvc源码解析的,写的很好,很详细。推荐去看

相关推荐
python开发_常用的python模块及安装方法
adodb:我们领导推荐的数据库连接组件bsddb3:BerkeleyDB的连接组件Cheetah-1.0:我比较喜欢这个版本的cheeta…
日期:2022-11-24 点赞:878 阅读:9,086
Educational Codeforces Round 11 C. Hard Process 二分
C. Hard Process题目连接:http://www.codeforces.com/contest/660/problem/CDes…
日期:2022-11-24 点赞:807 阅读:5,561
下载Ubuntn 17.04 内核源代码
zengkefu@server1:/usr/src$ uname -aLinux server1 4.10.0-19-generic #21…
日期:2022-11-24 点赞:569 阅读:6,410
可用Active Desktop Calendar V7.86 注册码序列号
可用Active Desktop Calendar V7.86 注册码序列号Name: www.greendown.cn Code: &nb…
日期:2022-11-24 点赞:733 阅读:6,183
Android调用系统相机、自定义相机、处理大图片
Android调用系统相机和自定义相机实例本博文主要是介绍了android上使用相机进行拍照并显示的两种方式,并且由于涉及到要把拍到的照片显…
日期:2022-11-24 点赞:512 阅读:7,820
Struts的使用
一、Struts2的获取  Struts的官方网站为:http://struts.apache.org/  下载完Struts2的jar包,…
日期:2022-11-24 点赞:671 阅读:4,903