首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >Spring MVC 中的 RootApplicationContext 和 WebApplicationContext

Spring MVC 中的 RootApplicationContext 和 WebApplicationContext

原创
作者头像
技术文章分析
发布2025-09-21 15:27:27
发布2025-09-21 15:27:27
10500
代码可运行
举报
文章被收录于专栏:技术技术
运行总次数:0
代码可运行

在 Spring MVC 应用中,理解 RootApplicationContextWebApplicationContext 这两个应用上下文(Application Context)的区别和关系,是掌握 Spring MVC 架构的关键。它们共同构成了 Spring Web 应用的 IoC 容器层次结构。


一、核心概念

1.1 为什么需要两个上下文?

Spring MVC 应用通常包含不同类型的组件:

  • 业务逻辑组件:Service、Repository (DAO)、数据源、事务管理器等。这些组件与 Web 层无关,是整个应用的核心。
  • Web 层组件:Controller、HandlerMapping、ViewResolver、MultipartResolver 等。这些组件专门处理 HTTP 请求和响应。

将这两类组件分离到不同的上下文中,可以实现:

  • 职责分离:业务逻辑与 Web 层解耦。
  • 可重用性RootApplicationContext 中的业务 Bean 可以被多个 WebApplicationContext(如不同的 Servlet)共享。
  • 更好的配置管理:可以分别配置核心服务和 Web 组件。
代码语言:javascript
代码运行次数:0
运行
复制
CCTV.PCFANGYUANKOU.COM37丨JRS.XUANYAJU.CN50丨FOOTBALL.HASUNSOFT.COM52丨OUGUAN.HECHENGTAOLI.COM81
ONLINE.GDYFDGC.CN68丨SWEET.RUNAIBIOTECH.COM29丨JRS.GCYMGS.CN90丨ONLINE.IPASC.CN19
NBA.FJDDSD.COM11丨XIJIA.BRANDAGRI.COM33丨LIVE.CHANGTAI333.COM71丨ZHIBO.FUWANG1688.COM21
MOBI.JNSDPMJ.COM97丨YES.SANGONGZY.COM20丨CCTV.GYZXSJ.COM83丨SHARE.YMLYTZ.COM42
ONLINE.BOTIANQI.COM52丨ZUQIU.BTJZ.NET.CN56丨FOOTBALL.0518XZW.COM45丨GDYFDGC.CN85
M.DFYXBJ.CN14丨ONLINE.SZ-EDC.COM28丨L.FQW.INFO80丨VIP.TCCQLXS.CN18
ZHIBO.HZBESTSEO.COM37丨SHARE.HZTENGHONG.COM72丨ZB.XINGJIJIN.ORG.CN48丨MOBI.SNQCZ.COM27
VIP.FJFYW.NET68丨BOLL.XIANGHETL.COM15丨TV.FMMITV.COM46丨CCTV.CQPXY.COM97
QQ.HAXFDC.COM77丨SJB.HZSMC.COM89丨WEIBO.DIJIUXIAOXUE.COM74丨IQIYI.SZ-EDC.COM19
WAP.FJFYW.NET42丨MAP.AIIN.ORG.CN38丨ZHIBO.HBST123.COM58丨JRS.GZBYJULEBU.COM53
M.RSEYEPRO.COM51丨ZHIBO8.SEO-YUN.COM10丨SHARE.BOTIANQI.COM83丨IQIYI.KEYUQZJX.COM71
VIP.HASUNSOFT.COM25丨SAISHI.GDYFDGC.CN99丨SINA.YCYKJ.NET87丨ZB.HZBESTSEO.COM91

二、两个上下文的定义与关系

2.1 RootApplicationContext (根应用上下文)

  • 作用:这是 Spring MVC 应用的父上下文。它负责管理非 Web 层的、全局的业务组件
  • 包含的 Bean
    • @Service 注解的 Service 类
    • @Repository 注解的 DAO/Repository 类
    • 数据源 (DataSource)
    • 事务管理器 (PlatformTransactionManager)
    • JPA/Hibernate 实体管理器 (EntityManagerFactory)
    • 缓存配置
    • 邮件服务等
  • 生命周期:在 Web 应用启动时创建,在应用关闭时销毁。
  • 配置方式:通常通过 ContextLoaderListener 加载,配置文件如 applicationContext.xml 或 Java 配置类。

2.2 WebApplicationContext (Web 应用上下文)

  • 作用:这是 Spring MVC 的子上下文,专门负责管理Web 层的组件。它继承RootApplicationContext 的所有 Bean。
  • 包含的 Bean
    • @Controller@RestController 注解的控制器
    • HandlerMapping (处理请求映射)
    • HandlerAdapter (调用处理器)
    • ViewResolver (解析视图名称)
    • MultipartResolver (处理文件上传)
    • HandlerExceptionResolver (处理异常)
    • LocaleResolver (处理国际化)
    • ThemeResolver (处理主题)
  • 生命周期:由 DispatcherServlet 创建和管理。一个应用可以有多个 DispatcherServlet,每个都有自己的 WebApplicationContext
  • 配置方式:由 DispatcherServlet 加载,配置文件如 [servlet-name]-servlet.xml 或通过 @EnableWebMvc 的 Java 配置。

2.3 继承关系

代码语言:javascript
代码运行次数:0
运行
复制
                             +-------------------------+
                             |   RootApplicationContext  |
                             | (父上下文)               |
                             | - Service Beans         |
                             | - Repository Beans      |
                             | - DataSource            |
                             | - TransactionManager    |
                             +------------+------------+
                                          |
                                          | 继承 (可访问)
                                          v
                             +-------------------------+
                             |   WebApplicationContext   |
                             | (子上下文)               |
                             | - Controller Beans      |
                             | - ViewResolver          |
                             | - HandlerMapping        |
                             | - ...                   |
                             +-------------------------+
  • 子上下文可以访问父上下文中的所有 Bean。因此,Controller 可以直接 @Autowired Service
  • 父上下文不能访问子上下文中的 BeanService 无法直接访问 ViewResolverController
  • Bean 名称冲突:如果父子上下文中有同名的 Bean,子上下文的 Bean 会覆盖父上下文的 Bean(不推荐这样做)。

三、配置方式详解

3.1 基于 XML 的配置

web.xml (Web 应用部署描述符)
代码语言:javascript
代码运行次数:0
运行
复制
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee 
                             http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
         version="4.0">

    <!-- 1. 配置 ContextLoaderListener (创建 RootApplicationContext) -->
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>

    <!-- 指定 RootApplicationContext 的配置文件位置 -->
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>/WEB-INF/applicationContext.xml</param-value>
        <!-- 
             也可以使用多个文件: 
             <param-value>
                 /WEB-INF/applicationContext.xml,
                 /WEB-INF/security-context.xml
             </param-value>
        -->
    </context-param>

    <!-- 2. 配置 DispatcherServlet (创建 WebApplicationContext) -->
    <servlet>
        <servlet-name>dispatcher</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <!-- 
             DispatcherServlet 默认会加载 [servlet-name]-servlet.xml
             这里明确指定配置文件位置
        -->
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>/WEB-INF/dispatcher-servlet.xml</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>

    <servlet-mapping>
        <servlet-name>dispatcher</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>

</web-app>
applicationContext.xml (Root Context 配置)
代码语言:javascript
代码运行次数:0
运行
复制
<!-- /WEB-INF/applicationContext.xml -->
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:tx="http://www.springframework.org/schema/tx"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
                           http://www.springframework.org/schema/beans/spring-beans.xsd
                           http://www.springframework.org/schema/context
                           http://www.springframework.org/schema/context/spring-context.xsd
                           http://www.springframework.org/schema/tx
                           http://www.springframework.org/schema/tx/spring-tx.xsd">

    <!-- 扫描 Service 和 Repository 组件 -->
    <context:component-scan base-package="com.example.service, com.example.repository" />

    <!-- 数据源配置 (示例) -->
    <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
        <property name="driverClassName" value="com.mysql.cj.jdbc.Driver"/>
        <property name="url" value="jdbc:mysql://localhost:3306/mydb"/>
        <property name="username" value="root"/>
        <property name="password" value="password"/>
    </bean>

    <!-- JdbcTemplate (可选) -->
    <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
        <property name="dataSource" ref="dataSource"/>
    </bean>

    <!-- 事务管理器 -->
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource"/>
    </bean>

    <!-- 启用注解驱动的事务管理 -->
    <tx:annotation-driven transaction-manager="transactionManager"/>

</beans>
dispatcher-servlet.xml (Web Context 配置)
代码语言:javascript
代码运行次数:0
运行
复制
<!-- /WEB-INF/dispatcher-servlet.xml -->
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:mvc="http://www.springframework.org/schema/mvc"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
                           http://www.springframework.org/schema/beans/spring-beans.xsd
                           http://www.springframework.org/schema/context
                           http://www.springframework.org/schema/context/spring-context.xsd
                           http://www.springframework.org/schema/mvc
                           http://www.springframework.org/schema/mvc/spring-mvc.xsd">

    <!-- 扫描 Controller 组件 -->
    <context:component-scan base-package="com.example.controller" />

    <!-- 启用 Spring MVC 注解驱动 -->
    <!-- 等价于配置了 DefaultAnnotationHandlerMapping, 
         AnnotationMethodHandlerAdapter 等核心组件 -->
    <mvc:annotation-driven />

    <!-- 配置视图解析器 (例如 JSP) -->
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix" value="/WEB-INF/views/" />
        <property name="suffix" value=".jsp" />
    </bean>

    <!-- 处理静态资源 (CSS, JS, Images) -->
    <mvc:resources location="/static/" mapping="/static/**" />

</beans>

3.2 基于 Java 配置 (现代推荐方式)

WebApplicationInitializer (替代 web.xml)
代码语言:javascript
代码运行次数:0
运行
复制
// com/example/config/WebAppInitializer.java
package com.example.config;

import org.springframework.web.WebApplicationInitializer;
import org.springframework.web.context.ContextLoaderListener;
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
import org.springframework.web.servlet.DispatcherServlet;

import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletRegistration;

public class WebAppInitializer implements WebApplicationInitializer {

    @Override
    public void onStartup(ServletContext servletContext) throws ServletException {
        // 1. 创建 Root WebApplicationContext
        AnnotationConfigWebApplicationContext rootContext = new AnnotationConfigWebApplicationContext();
        rootContext.register(RootConfig.class); // 注册 Root 配置类

        // 2. 将 Root Context 添加为 ServletContext 的监听器
        servletContext.addListener(new ContextLoaderListener(rootContext));

        // 3. 创建 DispatcherServlet 的 WebApplicationContext
        AnnotationConfigWebApplicationContext dispatcherContext = new AnnotationConfigWebApplicationContext();
        dispatcherContext.register(WebConfig.class); // 注册 Web 配置类

        // 4. 注册 DispatcherServlet
        ServletRegistration.Dynamic dispatcher = servletContext.addServlet("dispatcher", new DispatcherServlet(dispatcherContext));
        dispatcher.setLoadOnStartup(1);
        dispatcher.addMapping("/");
    }
}
RootConfig.java (根配置)
代码语言:javascript
代码运行次数:0
运行
复制
// com/example/config/RootConfig.java
package com.example.config;

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.FilterType;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;

@Configuration
@ComponentScan(
    basePackages = "com.example",
    // 排除 @Controller, @RestController, @EnableWebMvc 的类
    excludeFilters = @ComponentScan.Filter(
        type = FilterType.ANNOTATION,
        classes = {org.springframework.stereotype.Controller.class, EnableWebMvc.class}
    )
)
public class RootConfig {
    // 数据源、事务、Service、Repository 等配置
}
WebConfig.java (Web 配置)
代码语言:javascript
代码运行次数:0
运行
复制
// com/example/config/WebConfig.java
package com.example.config;

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.ViewResolverRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@Configuration
@EnableWebMvc // 启用 Spring MVC 配置
@ComponentScan(basePackages = "com.example.controller") // 只扫描 Controller
public class WebConfig implements WebMvcConfigurer {

    // 配置视图解析器
    @Override
    public void configureViewResolvers(ViewResolverRegistry registry) {
        registry.jsp("/WEB-INF/views/", ".jsp");
    }

    // 其他 MVC 配置...
}

四、验证上下文关系

你可以在 Controller 中注入 ApplicationContext 来验证继承关系:

代码语言:javascript
代码运行次数:0
运行
复制
java深色版本@RestController
public class TestController {

    @Autowired
    private ApplicationContext webApplicationContext; // 这是 WebApplicationContext

    @GetMapping("/context-test")
    public String testContext() {
        // 获取父上下文
        ApplicationContext parentContext = webApplicationContext.getParent();
        if (parentContext != null) {
            return "Web Context 父上下文存在,Bean 数量: " + parentContext.getBeanDefinitionCount();
        } else {
            return "Web Context 没有父上下文!";
        }
    }
}

五、总结

特性

RootApplicationContext

WebApplicationContext

角色

父上下文 (Parent Context)

子上下文 (Child Context)

创建者

ContextLoaderListener

DispatcherServlet

主要职责

管理业务层、数据层组件 (Service, Repository, DataSource, TransactionManager)

管理 Web 层组件 (Controller, ViewResolver, HandlerMapping)

可访问性

不能 访问 WebApplicationContext 中的 Bean

可以 访问 RootApplicationContext 中的所有 Bean

配置文件

contextConfigLocation 参数指定 (如 applicationContext.xml)

[servlet-name]-servlet.xml 或 DispatcherServlet 的 contextConfigLocation

配置类

@Configuration 类被 ContextLoaderListener 加载

@Configuration 类被 DispatcherServlet 加载,通常带有 @EnableWebMvc

推荐扫描包

com.example.service, com.example.repository

com.example.controller

核心要点

  1. 分层清晰:业务逻辑与 Web 层分离。
  2. 继承关系WebApplicationContext 继承 RootApplicationContext,实现了依赖注入的传递性。
  3. 避免循环依赖:由于单向继承,避免了父子上下文间的循环依赖。
  4. 现代实践:优先使用基于 Java 的配置 (@Configuration) 和 WebApplicationInitializer,而非 XML。

理解这两个上下文,是构建结构清晰、易于维护的大型 Spring MVC 应用的基础。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一、核心概念
    • 1.1 为什么需要两个上下文?
  • 二、两个上下文的定义与关系
    • 2.1 RootApplicationContext (根应用上下文)
    • 2.2 WebApplicationContext (Web 应用上下文)
    • 2.3 继承关系
  • 三、配置方式详解
    • 3.1 基于 XML 的配置
      • web.xml (Web 应用部署描述符)
      • applicationContext.xml (Root Context 配置)
      • dispatcher-servlet.xml (Web Context 配置)
    • 3.2 基于 Java 配置 (现代推荐方式)
      • WebApplicationInitializer (替代 web.xml)
      • RootConfig.java (根配置)
      • WebConfig.java (Web 配置)
  • 四、验证上下文关系
  • 五、总结
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档