文章目录
前言
springmvc 有两个版本,一个是直接使用 springmvc,一个是通过 springboot 使用 springmvc。两者的启动流程是不一样的,主要是 Bean 的创建时机不同,直接使用 springpvc 时是通过 DispatcherServlet 带动 Spring 容器的启动,进而创建各种 Bean,而 springboot 的版本是先启动了 Spring 容器创建各种 Bean。
本文中记录的启动流程是 单独使用 springmvc 的版本。
springmvc 启动流程 - 大白话描述
整理的 springmvc 启动流程图:
图中步骤详解:
- Tomcat 是入口,所以先 Tomcat 启动。
- Tomcat 启动后,会加载项目中的 web.xml 文件。
- 在 web.xml 文件中,定义了 springmvc 的核心类 DispatcherServlet,所以 DispatcherServlet 最终会被加载
- 因为 DispatcherServlet 属于 Servlet,所以 Tomcat 会回调 DispatcherServlet 的 init 方法
- 在 init 方法中,会创建 WebApplicationContext 对象,这个对象其实就是 Spring 容器。
- 向 WebApplicationContext 对象中添加 refresh 的监听,这个监听很重要,后面会用它初始化核心组件。
- 调用 WebApplicationContext 的 refresh 方法。refresh 方法是 Spring 容器的核心方法,既启动容器。
- Srping 容器启动完毕后,会触发 第六步 添加的 refresh 监听。
- 在 refresh 监听中,会初始化 springmvc 的核心组件
- 调用 initHandlerMappings 方法,查找并添加 HandlerMapping,spingmvc 默认会从 DispatcherServlet.properties 中加载多个 HandlerMapping 为 Bean,HandlerMapping 的作用是在 Spring 容器中找到 Handler,并保存 Handler 和 请求路径 的映射关系。Handler 是自己定义的处理请求的逻辑,Handler 有多种写法,不同的写法会由对应的 HandlerMapping 处理。常见的 @RequestMapping 声明的 Handler 就是由 RequestMappingHandlerMapping 处理。RequestMappingHandlerMapping 也是重点研究对象。
因为 RequestMappingHandlerMapping 实现了 InitializingBean 接口,当 RequestMappingHandlerMapping 被创建为 Bean 后,会回调 InitializingBean 接口的 afterPropertiesSet 方法。在 afterPropertiesSet 方法内,RequestMappingHandlerMapping 会找到所有满足条件的 Handler 并保存 Handler 和 请求处理 的映射关系。 - 调用 initHandlerAdapters 方法,查找并添加 HandlerAdapter,spingmvc 默认会从 DispatcherServlet.properties 中加载多个 HandlerAdapter 为 Bean。因为 Handler 保存在 HandlerMapping 中,而每个 HandlerMapping 又是不同类型,HandlerAdapter 的作用就是在操作 Handler 时保证统一接口调用,这里使用了适配器模式。每种类型的 HandlerMapping 都会对应一个 HandlerAdapter。RequestMappingHandlerMapping 对应的就是 RequestMappingHandlerAdapter,RequestMappingHandlerAdapter 也是重点研究对象。
因为 RequestMappingHandlerAdapter 实现了 InitializingBean 接口,当 RequestMappingHandlerAdapter 被创建为 Bean 后,会回调 InitializingBean 接口的 afterPropertiesSet 方法。在 afterPropertiesSet 方法内 RequestMappingHandlerAdapter 会加载各种 方法参数处理器(MethodArgumentResolver) 和 方法返回值处理器 (MethodReturnValueHandler)。
@RequestMapping 声明的 Handler 有多种传参方式,如:@RequestParam、@RequestBody 等,每种传参方式都对应一个 方法参数处理器,
@RequestMapping 声明的 Handler 有多种返回方式,如:@ResponseBody、ModelAndView 等,每种返回方式都对应一个 方法返回值处理器 - 调用 initViewResolvers 方法,查找并添加 ViewResolver,springmvc 默认会从 DispatcherServlet.properties 中加载。常见的 InternalResourceViewResolver 就是 JSP 文件对应的视图解析器
springmvc 启动流程 - 关键源码
看完前面的启动流程,就基本掌握了核心原理,下面对关键源码进行列举。
1. 对应流程图中紫色部分
public abstract class HttpServletBean {
// Tomcat 回调 这个方法
public final void init() throws ServletException {
initServletBean();
}
}
public abstract class FrameworkServlet {
// 给 DispatcherServlet 添加 spring 容器
protected final void initServletBean() throws ServletException {
this.webApplicationContext = initWebApplicationContext();
}
protected WebApplicationContext initWebApplicationContext() {
if (wac == null) {
// 创建 spring 容器
wac = createWebApplicationContext(rootContext);
}
return wac;
}
protected WebApplicationContext createWebApplicationContext(@Nullable WebApplicationContext parent) {
// 创建 spring 容器
return createWebApplicationContext((ApplicationContext) parent);
}
protected WebApplicationContext createWebApplicationContext(@Nullable ApplicationContext parent) {
// 创建 spring 容器
configureAndRefreshWebApplicationContext(wac);
return wac;
}
protected void configureAndRefreshWebApplicationContext(ConfigurableWebApplicationContext wac) {
// 给 spring 容器 添加 refresh 监听
wac.addApplicationListener(new SourceFilteringListener(wac, new ContextRefreshListener()));
// 启动 spring 容器
wac.refresh();
}
}
2. 对应流程图中浅蓝色部分
public class DispatcherServlet {
// spring 容器启动完成后,回调 refresh 监听
protected void onRefresh(ApplicationContext context) {
initStrategies(context);
}
// 加载核心组件
protected void initStrategies(ApplicationContext context) {
// 查找 HandlerMapping
initHandlerMappings(context);
// 查找 HandlerAdapter
initHandlerAdapters(context);
// 查找 ViewResolver
initViewResolvers(context);
}
}
3. 对应流程图绿色部分
DispatcherServlet.properties
org.springframework.web.servlet.HandlerMapping=org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping,\
org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping,\
org.springframework.web.servlet.function.support.RouterFunctionMapping
public class DispatcherServlet {
private void initHandlerMappings(ApplicationContext context) {
if (this.handlerMappings == null) {
// 从 DispatcherServlet.properties 中查找 HandlerMapping
this.handlerMappings = getDefaultStrategies(context, HandlerMapping.class);
}
}
protected <T> List<T> getDefaultStrategies(ApplicationContext context, Class<T> strategyInterface) {
// 从 DispatcherServlet.properties 中查找 HandlerMapping
ClassPathResource resource = new ClassPathResource(DEFAULT_STRATEGIES_PATH, DispatcherServlet.class);
// 将找到的 HandlerMapping 创建为 Bean
Object strategy = createDefaultStrategy(context, clazz);
}
public class RequestMappingHandlerMapping {
// 创建 RequestMappingHandlerMapping 为 Bean 后的回调
public void afterPropertiesSet() {
// 查找使用了 @RequestMapping 注解的 Bean,并注册为 Handler
super.afterPropertiesSet();
}
// afterPropertiesSet 最终会调到这里,查找使用了 @RequestMapping 注解的 Bean,并注册为 Handler
private RequestMappingInfo createRequestMappingInfo(AnnotatedElement element) {
List<AnnotationDescriptor> requestMappings = descriptors.stream()
.filter(desc -> desc.annotation instanceof RequestMapping).toList();
requestMappingInfo = createRequestMappingInfo((RequestMapping) requestMappings.get(0).annotation, customCondition);
}
}
4. 对应流程图中浅黄色部分
org.springframework.web.servlet.HandlerAdapter=org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter,\
org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter,\
org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter,\
org.springframework.web.servlet.function.support.HandlerFunctionAdapter
public class DispatcherServlet {
private void initHandlerAdapters(ApplicationContext context) {
if (this.handlerAdapters == null) {
// 从 DispatcherServlet.properties 中查找 HandlerAdapter
this.handlerAdapters = getDefaultStrategies(context, HandlerAdapter.class);
}
}
protected <T> List<T> getDefaultStrategies(ApplicationContext context, Class<T> strategyInterface) {
// 从 DispatcherServlet.properties 中查找 HandlerAdapter
ClassPathResource resource = new ClassPathResource(DEFAULT_STRATEGIES_PATH, DispatcherServlet.class);
// 将找到的 HandlerAdapter 创建为 Bean
Object strategy = createDefaultStrategy(context, clazz);
}
public class RequestMappingHandlerAdapter {
// 创建 RequestMappingHandlerAdapter 为 Bean 后的回调
public void afterPropertiesSet() {
// 查找 方法参数解析器
if (this.argumentResolvers == null) {
List<HandlerMethodArgumentResolver> resolvers = getDefaultArgumentResolvers();
this.argumentResolvers = new HandlerMethodArgumentResolverComposite().addResolvers(resolvers);
}
// 查找 方法返回解析器
if (this.returnValueHandlers == null) {
List<HandlerMethodReturnValueHandler> handlers = getDefaultReturnValueHandlers();
this.returnValueHandlers = new HandlerMethodReturnValueHandlerComposite().addHandlers(handlers);
}
}
// 默认的参数解析器
private List<HandlerMethodArgumentResolver> getDefaultArgumentResolvers() {
List<HandlerMethodArgumentResolver> resolvers = new ArrayList<>(30);
resolvers.add(new RequestParamMethodArgumentResolver(getBeanFactory(), false));
resolvers.add(new RequestParamMapMethodArgumentResolver());
resolvers.add(new PathVariableMethodArgumentResolver());
resolvers.add(new PathVariableMapMethodArgumentResolver());
resolvers.add(new MatrixVariableMethodArgumentResolver());
resolvers.add(new MatrixVariableMapMethodArgumentResolver());
resolvers.add(new ServletModelAttributeMethodProcessor(false));
resolvers.add(new RequestResponseBodyMethodProcessor(getMessageConverters(), this.requestResponseBodyAdvice));
resolvers.add(new RequestPartMethodArgumentResolver(getMessageConverters(), this.requestResponseBodyAdvice));
resolvers.add(new RequestHeaderMethodArgumentResolver(getBeanFactory()));
resolvers.add(new RequestHeaderMapMethodArgumentResolver());
resolvers.add(new ServletCookieValueMethodArgumentResolver(getBeanFactory()));
resolvers.add(new ExpressionValueMethodArgumentResolver(getBeanFactory()));
resolvers.add(new SessionAttributeMethodArgumentResolver());
resolvers.add(new RequestAttributeMethodArgumentResolver());
resolvers.add(new ServletRequestMethodArgumentResolver());
resolvers.add(new ServletResponseMethodArgumentResolver());
resolvers.add(new HttpEntityMethodProcessor(getMessageConverters(), this.requestResponseBodyAdvice));
resolvers.add(new RedirectAttributesMethodArgumentResolver());
resolvers.add(new ModelMethodProcessor());
resolvers.add(new MapMethodProcessor());
resolvers.add(new ErrorsMethodArgumentResolver());
resolvers.add(new SessionStatusMethodArgumentResolver());
resolvers.add(new UriComponentsBuilderMethodArgumentResolver());
if (KotlinDetector.isKotlinPresent()) {
resolvers.add(new ContinuationHandlerMethodArgumentResolver());
}
if (getCustomArgumentResolvers() != null) {
resolvers.addAll(getCustomArgumentResolvers());
}
resolvers.add(new PrincipalMethodArgumentResolver());
resolvers.add(new RequestParamMethodArgumentResolver(getBeanFactory(), true));
resolvers.add(new ServletModelAttributeMethodProcessor(true));
return resolvers;
}
// 默认的方法返回解析器
private List<HandlerMethodReturnValueHandler> getDefaultReturnValueHandlers() {
List<HandlerMethodReturnValueHandler> handlers = new ArrayList<>(20);
handlers.add(new ModelAndViewMethodReturnValueHandler());
handlers.add(new ModelMethodProcessor());
handlers.add(new ViewMethodReturnValueHandler());
handlers.add(new ResponseBodyEmitterReturnValueHandler(getMessageConverters(),
this.reactiveAdapterRegistry, this.taskExecutor, this.contentNegotiationManager,
initViewResolvers(), initLocaleResolver()));
handlers.add(new StreamingResponseBodyReturnValueHandler());
handlers.add(new HttpEntityMethodProcessor(getMessageConverters(),
this.contentNegotiationManager, this.requestResponseBodyAdvice, this.errorResponseInterceptors));
handlers.add(new HttpHeadersReturnValueHandler());
handlers.add(new CallableMethodReturnValueHandler());
handlers.add(new DeferredResultMethodReturnValueHandler());
handlers.add(new AsyncTaskMethodReturnValueHandler(this.beanFactory));
handlers.add(new ServletModelAttributeMethodProcessor(false));
handlers.add(new RequestResponseBodyMethodProcessor(getMessageConverters(),
this.contentNegotiationManager, this.requestResponseBodyAdvice, this.errorResponseInterceptors));
handlers.add(new ViewNameMethodReturnValueHandler());
handlers.add(new MapMethodProcessor());
if (getCustomReturnValueHandlers() != null) {
handlers.addAll(getCustomReturnValueHandlers());
}
if (!CollectionUtils.isEmpty(getModelAndViewResolvers())) {
handlers.add(new ModelAndViewResolverMethodReturnValueHandler(getModelAndViewResolvers()));
}
else {
handlers.add(new ServletModelAttributeMethodProcessor(true));
}
return handlers;
}
}
5. 对应流程图中的橙黄色部分
org.springframework.web.servlet.ViewResolver=org.springframework.web.servlet.view.InternalResourceViewResolver
public class DispatcherServlet {
private void initViewResolvers(ApplicationContext context) {
if (this.viewResolvers == null) {
// 从 DispatcherServlet.properties 中查找 ViewResolver
this.viewResolvers = getDefaultStrategies(context, ViewResolver.class);
}
}
protected <T> List<T> getDefaultStrategies(ApplicationContext context, Class<T> strategyInterface) {
// 从 DispatcherServlet.properties 中查找 ViewResolver
ClassPathResource resource = new ClassPathResource(DEFAULT_STRATEGIES_PATH, DispatcherServlet.class);
// 将找到的 ViewResolver 创建为 Bean
Object strategy = createDefaultStrategy(context, clazz);
}
}