Spring MVC 初始化
1. DispatcherServlet 的初始化流程
DispatcherServlet
是 Spring MVC 的核心入口,负责接收 HTTP 请求并将其分发给相应的处理器。它的初始化过程从 HttpServlet
的生命周期方法 init()
开始。
1.1 HttpServletBean 的 init()
方法
DispatcherServlet
继承自 FrameworkServlet
,而 FrameworkServlet
又继承自 HttpServletBean
。HttpServletBean
的 init()
方法是初始化的起点。
@Override
public final void init() throws ServletException {
// 1. 解析 Servlet 的初始化参数,并将其注入到 DispatcherServlet 的 Bean 属性中
PropertyValues pvs = new ServletConfigPropertyValues(getServletConfig(), this.requiredProperties);
BeanWrapper bw = PropertyAccessorFactory.forBeanPropertyAccess(this);
ResourceLoader resourceLoader = new ServletContextResourceLoader(getServletContext());
bw.registerCustomEditor(Resource.class, new ResourceEditor(resourceLoader, getEnvironment()));
initBeanWrapper(bw);
bw.setPropertyValues(pvs, true);
// 2. 调用子类的初始化方法
initServletBean();
}
ServletConfigPropertyValues
:解析web.xml
中配置的 Servlet 初始化参数(如contextConfigLocation
)。BeanWrapper
:将解析后的参数注入到DispatcherServlet
的 Bean 属性中。initServletBean()
:调用子类FrameworkServlet
的初始化方法。
1.2 FrameworkServlet 的 initServletBean()
方法
FrameworkServlet
的 initServletBean()
方法负责初始化 Spring 的 WebApplicationContext
。
@Override
protected final void initServletBean() throws ServletException {
// 初始化 WebApplicationContext
this.webApplicationContext = initWebApplicationContext();
initFrameworkServlet();
}
initWebApplicationContext()
:创建或获取WebApplicationContext
。initFrameworkServlet()
:空方法,留给子类扩展。
1.3 initWebApplicationContext()
方法
initWebApplicationContext()
是 FrameworkServlet
的核心方法,负责创建或获取 WebApplicationContext
。
protected WebApplicationContext initWebApplicationContext() {
// 1. 获取根 WebApplicationContext(通常是通过 ContextLoaderListener 加载的)
WebApplicationContext rootContext = WebApplicationContextUtils.getWebApplicationContext(getServletContext());
WebApplicationContext wac = null;
// 2. 如果已经通过构造方法或 setter 注入了 WebApplicationContext,则直接使用
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);
}
configureAndRefreshWebApplicationContext(cwac);
}
}
}
// 3. 如果没有显式注入 WebApplicationContext,则尝试从 ServletContext 中查找
if (wac == null) {
wac = findWebApplicationContext();
}
// 4. 如果仍然没有找到,则创建一个新的 WebApplicationContext
if (wac == null) {
wac = createWebApplicationContext(rootContext);
}
// 5. 触发刷新事件
if (!this.refreshEventReceived) {
onRefresh(wac);
}
return wac;
}
rootContext
:通过ContextLoaderListener
加载的根上下文(通常是 Spring 的父容器)。createWebApplicationContext()
:创建新的WebApplicationContext
,默认实现是XmlWebApplicationContext
或AnnotationConfigWebApplicationContext
。onRefresh()
:在WebApplicationContext
刷新时调用,DispatcherServlet
会在此方法中初始化各种策略组件。
2. DispatcherServlet 的策略组件初始化
DispatcherServlet
的核心功能依赖于一系列策略组件,如 HandlerMapping
、HandlerAdapter
、ViewResolver
等。这些组件的初始化在 onRefresh()
方法中完成。
2.1 onRefresh()
方法
onRefresh()
是 DispatcherServlet
初始化的核心方法,负责初始化所有策略组件。
@Override
protected void onRefresh(ApplicationContext context) {
initStrategies(context);
}
protected void initStrategies(ApplicationContext context) {
initMultipartResolver(context); // 初始化文件上传解析器
initLocaleResolver(context); // 初始化本地化解析器
initThemeResolver(context); // 初始化主题解析器
initHandlerMappings(context); // 初始化处理器映射器
initHandlerAdapters(context); // 初始化处理器适配器
initHandlerExceptionResolvers(context); // 初始化异常解析器
initRequestToViewNameTranslator(context); // 初始化请求到视图名的转换器
initViewResolvers(context); // 初始化视图解析器
initFlashMapManager(context); // 初始化 FlashMap 管理器
}
2.2 initHandlerMappings()
方法
HandlerMapping
负责将请求映射到相应的处理器(Controller)。DispatcherServlet
会从 WebApplicationContext
中获取所有类型为 HandlerMapping
的 Bean。
private void initHandlerMappings(ApplicationContext context) {
this.handlerMappings = null;
// 1. 是否检测所有 HandlerMapping Bean
if (this.detectAllHandlerMappings) {
Map<String, HandlerMapping> matchingBeans = BeanFactoryUtils.beansOfTypeIncludingAncestors(
context, HandlerMapping.class, true, false);
if (!matchingBeans.isEmpty()) {
this.handlerMappings = new ArrayList<>(matchingBeans.values());
AnnotationAwareOrderComparator.sort(this.handlerMappings);
}
} else {
// 2. 只检测名为 "handlerMapping" 的 Bean
try {
HandlerMapping hm = context.getBean(HANDLER_MAPPING_BEAN_NAME, HandlerMapping.class);
this.handlerMappings = Collections.singletonList(hm);
} catch (NoSuchBeanDefinitionException ex) {
// 忽略,稍后会使用默认策略
}
}
// 3. 如果没有找到 HandlerMapping,则使用默认策略
if (this.handlerMappings == null) {
this.handlerMappings = getDefaultStrategies(context, HandlerMapping.class);
}
}
-
默认策略:如果没有显式配置
HandlerMapping
,Spring MVC 会使用DispatcherServlet.properties
中定义的默认策略:org.springframework.web.servlet.HandlerMapping=org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping,\ org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping
2.3 initHandlerAdapters()
方法
HandlerAdapter
负责调用处理器(Controller)的方法。DispatcherServlet
会从 WebApplicationContext
中获取所有类型为 HandlerAdapter
的 Bean。
private void initHandlerAdapters(ApplicationContext context) {
this.handlerAdapters = null;
// 1. 是否检测所有 HandlerAdapter Bean
if (this.detectAllHandlerAdapters) {
Map<String, HandlerAdapter> matchingBeans = BeanFactoryUtils.beansOfTypeIncludingAncestors(
context, HandlerAdapter.class, true, false);
if (!matchingBeans.isEmpty()) {
this.handlerAdapters = new ArrayList<>(matchingBeans.values());
AnnotationAwareOrderComparator.sort(this.handlerAdapters);
}
} else {
// 2. 只检测名为 "handlerAdapter" 的 Bean
try {
HandlerAdapter ha = context.getBean(HANDLER_ADAPTER_BEAN_NAME, HandlerAdapter.class);
this.handlerAdapters = Collections.singletonList(ha);
} catch (NoSuchBeanDefinitionException ex) {
// 忽略,稍后会使用默认策略
}
}
// 3. 如果没有找到 HandlerAdapter,则使用默认策略
if (this.handlerAdapters == null) {
this.handlerAdapters = getDefaultStrategies(context, HandlerAdapter.class);
}
}
-
默认策略:如果没有显式配置
HandlerAdapter
,Spring MVC 会使用DispatcherServlet.properties
中定义的默认策略: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
2.4 initViewResolvers()
方法
ViewResolver
负责将逻辑视图名称解析为实际的视图对象。DispatcherServlet
会从 WebApplicationContext
中获取所有类型为 ViewResolver
的 Bean。
private void initViewResolvers(ApplicationContext context) {
this.viewResolvers = null;
// 1. 是否检测所有 ViewResolver Bean
if (this.detectAllViewResolvers) {
Map<String, ViewResolver> matchingBeans = BeanFactoryUtils.beansOfTypeIncludingAncestors(
context, ViewResolver.class, true, false);
if (!matchingBeans.isEmpty()) {
this.viewResolvers = new ArrayList<>(matchingBeans.values());
AnnotationAwareOrderComparator.sort(this.viewResolvers);
}
} else {
// 2. 只检测名为 "viewResolver" 的 Bean
try {
ViewResolver vr = context.getBean(VIEW_RESOLVER_BEAN_NAME, ViewResolver.class);
this.viewResolvers = Collections.singletonList(vr);
} catch (NoSuchBeanDefinitionException ex) {
// 忽略,稍后会使用默认策略
}
}
// 3. 如果没有找到 ViewResolver,则使用默认策略
if (this.viewResolvers == null) {
this.viewResolvers = getDefaultStrategies(context, ViewResolver.class);
}
}
-
默认策略:如果没有显式配置
ViewResolver
,Spring MVC 会使用DispatcherServlet.properties
中定义的默认策略:org.springframework.web.servlet.ViewResolver=org.springframework.web.servlet.view.InternalResourceViewResolver
3. 总结
Spring MVC 的初始化过程可以概括为以下几个步骤:
DispatcherServlet
初始化:从HttpServletBean
的init()
方法开始,解析 Servlet 配置并注入属性。WebApplicationContext
初始化:创建或获取 Spring 的上下文环境。- 策略组件初始化:在
onRefresh()
方法中初始化HandlerMapping
、HandlerAdapter
、ViewResolver
等核心组件。 - 默认策略:如果没有显式配置组件,Spring MVC 会使用
DispatcherServlet.properties
中定义的默认策略。
通过深入源码分析,我们可以清晰地看到 Spring MVC 的初始化流程及其核心组件的加载过程。这为我们在实际开发中自定义和扩展 Spring MVC 提供了坚实的基础。
· [翻译] 为什么 Tracebit 用 C# 开发
· 腾讯ima接入deepseek-r1,借用别人脑子用用成真了~
· Deepseek官网太卡,教你白嫖阿里云的Deepseek-R1满血版
· DeepSeek崛起:程序员“饭碗”被抢,还是职业进化新起点?
· RFID实践——.NET IoT程序读取高频RFID卡/标签