spring mvc容器初始化核心是区分根上下文(加载service/dao等)与mvc上下文(加载@controller等),通过web.xml配置contextloaderlistener和dispatcherservlet,或用webapplicationinitializer接口实现java配置,二者均确保dispatcherservlet为根上下文的子容器以实现依赖单向注入。

Spring MVC 的容器上下文初始化,核心在于区分 根应用上下文(Root Context) 和 MVC 上下文(Servlet Context)。web.xml 是传统 XML 方式,WebApplicationInitializer 是 Servlet 3.0+ 的 Java 配置方式,二者目标一致:注册 DispatcherServlet 并为其配置对应的 WebApplicationContext。
web.xml 方式:显式声明 ContextLoaderListener 和 DispatcherServlet
这是最经典的方式,适用于 Servlet 容器(如 Tomcat)且未完全迁移到纯 Java 配置的项目。
-
ContextLoaderListener 负责加载根上下文(通常放 service、dao、数据源等非 Web 层 Bean),通过
contextConfigLocation指定配置文件(如applicationContext.xml) -
DispatcherServlet 负责加载 MVC 上下文(放 @Controller、@RequestMapping、ViewResolver 等 Web 相关 Bean),其
contextConfigLocation可指定spring-mvc.xml,也可留空让 Spring 自动扫描带@Configuration的类 - DispatcherServlet 的
load-on-startup设为 1,确保早于其他 Servlet 初始化
示例片段:
WebApplicationInitializer 方式:用 Java 代码替代 web.xml
Servlet 3.0+ 容器支持,Spring 提供了 WebApplicationInitializer 接口(常继承 AbstractAnnotationConfigDispatcherServletInitializer),适合纯注解驱动项目。
-
getRootConfigClasses()返回根上下文的 Java 配置类(如AppConfig.class),对应原 ContextLoaderListener -
getServletConfigClasses()返回 MVC 上下文的配置类(如WebConfig.class),对应 DispatcherServlet 的 context -
getServletMappings()指定 DispatcherServlet 的 URL 映射(如"/") - 无需 web.xml,容器启动时自动发现并执行该初始化器
典型实现:
public class MyWebAppInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {@Override
protected Class>[] getRootConfigClasses() {
return new Class[]{AppConfig.class}; // service, dao, datasource
}
@Override
protected Class>[] getServletConfigClasses() {
return new Class[]{WebConfig.class}; // @Controller, ViewResolver, etc.
}
@Override
protected String[] getServletMappings() {
return new String[]{"/"};
}
}
关键细节:两个上下文的关系与隔离
DispatcherServlet 持有的 WebApplicationContext 是根上下文的子容器 —— 它能访问根容器中的 Bean(如 Service),但根容器无法访问 MVC 容器中的 Bean(如 Controller)。这种设计保障了分层清晰和依赖单向性。
- 若在
@Controller中注入@Service,只要 Service 在根上下文中定义,就能成功注入 - 不要在根配置类中扫描
@Controller;也不要在 Web 配置类中重复定义数据源或事务管理器 - 使用
@ComponentScan时注意 basePackages 区分,例如:
根配置类:@ComponentScan("com.example.service")
Web 配置类:@ComponentScan("com.example.web")
现代简化:Spring Boot 下的隐式初始化
虽然问题聚焦传统 Spring MVC,但值得提一句:Spring Boot 默认不使用 web.xml 或手动写 WebApplicationInitializer。它通过 SpringServletContainerInitializer + 自动配置机制,在内嵌容器启动时自动注册 DispatcherServlet,并按约定加载 @SpringBootApplication 类作为根上下文,同时启用 WebMvcAutoConfiguration 构建 MVC 环境。开发者只需关注 @Configuration 类和组件扫描即可。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











