SpringBoot和SpringMvc中的Context
字数 1551 2025-08-26 22:11:45

SpringBoot和SpringMVC中的Context详解

前言

在学习内存马技术时,经常会遇到Spring框架中的ChildContext和RootContext概念,这些概念对于理解Spring的上下文机制至关重要。本文将详细解析Spring MVC和Spring Boot中的上下文结构差异。

基本概念

ContextLoaderListener和DispatcherServlet

在传统Spring MVC应用中,通常使用两个关键组件来加载不同的Spring配置文件:

  1. ContextLoaderListener:加载applicationContext.xml,对应Root WebApplicationContext
  2. DispatcherServlet:加载servlet-context.xml,对应Child WebApplicationContext

父子上下文关系

  • RootContext:由ContextLoaderListener创建,是整个应用的父上下文
  • ChildContext:由DispatcherServlet创建,是子上下文,可以有多个
  • 两者是继承关系,ChildContext可以通过getParent()方法获取到RootContext

Spring MVC中的上下文机制

上下文获取方式

  1. 获取RootContext
WebApplicationContext root = ContextLoader.getCurrentWebApplicationContext();
  1. 通过ServletContext获取RootContext
ServletContext servletContext = root.getServletContext();
WebApplicationContext root = (WebApplicationContext)servletContext.getAttribute(
    WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE);
  1. 获取ChildContext
WebApplicationContext child = (WebApplicationContext)request.getAttribute(
    DispatcherServlet.WEB_APPLICATION_CONTEXT_ATTRIBUTE);

上下文特性验证

// 验证RootContext和ChildContext的关系
System.out.println("is parent==" + (child.getParent() == root));

// 检查Bean存在性
System.out.println("root:" + root.containsLocalBean("myService")); // false
System.out.println("child:" + child.containsLocalBean("myService")); // true

关键发现

  1. RootContext无法访问ChildContext中的Bean
  2. ChildContext可以访问RootContext中的Bean
  3. Bean名称存储时首字母会转为小写

Spring Boot中的上下文机制

与Spring MVC的主要区别

  1. 单一上下文:Spring Boot中只有一个RootContext,没有ChildContext
  2. 所有Bean都注册在这个单一的上下文中
  3. 获取方式不同
// 获取Spring Boot的RootContext
WebApplicationContext context = WebApplicationContextUtils.getWebApplicationContext(
    RequestContextUtils.findWebApplicationContext(
        ((ServletRequestAttributes)RequestContextHolder.currentRequestAttributes())
        .getRequest()).getServletContext());

上下文类型

Spring Boot中使用的是AnnotationConfigServletWebApplicationContext,其parent为null,表明它是RootContext。

配置文件的对应关系

Spring MVC典型配置

  1. RootContext配置
<context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>classpath:applicationContext.xml</param-value>
</context-param>
<listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
  1. ChildContext配置
<servlet>
    <servlet-name>springmvc</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <load-on-startup>1</load-on-startup>
    <init-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:dispatcherServlet.xml</param-value>
    </init-param>
</servlet>

Bean扫描规则

在哪个配置文件中声明注解扫描标签,扫描到的Bean就会被注册到对应的上下文中:

<context:component-scan base-package="Controller"/>

总结对比

相同点

  1. ServletContext都是ApplicationContextFacade对象
  2. 作用范围都是ServletContext最大,其他Context都是它的属性

不同点

特性 Spring MVC Spring Boot
上下文数量 多个(1个Root + n个Child) 单一RootContext
Bean存储 分散在不同上下文中 全部存储在单一上下文中
获取方式 有多种获取特定上下文的方法 统一获取方式

实际应用意义

  1. 内存马注入:通常选择获取ChildContext而非RootContext,因为ChildContext可以访问更多资源
  2. Bean查找:需要注意Bean名称的首字母小写规则
  3. 上下文隔离:理解父子上下文关系有助于设计合理的应用结构

参考资源

  1. Spring官方文档
  2. CSDN相关文章

通过深入理解Spring的上下文机制,开发者可以更好地掌握框架的核心原理,为高级应用和问题排查打下坚实基础。

SpringBoot和SpringMVC中的Context详解 前言 在学习内存马技术时,经常会遇到Spring框架中的ChildContext和RootContext概念,这些概念对于理解Spring的上下文机制至关重要。本文将详细解析Spring MVC和Spring Boot中的上下文结构差异。 基本概念 ContextLoaderListener和DispatcherServlet 在传统Spring MVC应用中,通常使用两个关键组件来加载不同的Spring配置文件: ContextLoaderListener :加载applicationContext.xml,对应Root WebApplicationContext DispatcherServlet :加载servlet-context.xml,对应Child WebApplicationContext 父子上下文关系 RootContext :由ContextLoaderListener创建,是整个应用的父上下文 ChildContext :由DispatcherServlet创建,是子上下文,可以有多个 两者是继承关系,ChildContext可以通过 getParent() 方法获取到RootContext Spring MVC中的上下文机制 上下文获取方式 获取RootContext : 通过ServletContext获取RootContext : 获取ChildContext : 上下文特性验证 关键发现 RootContext无法访问ChildContext中的Bean ChildContext可以访问RootContext中的Bean Bean名称存储时首字母会转为小写 Spring Boot中的上下文机制 与Spring MVC的主要区别 单一上下文 :Spring Boot中只有一个RootContext,没有ChildContext 所有Bean 都注册在这个单一的上下文中 获取方式不同 : 上下文类型 Spring Boot中使用的是 AnnotationConfigServletWebApplicationContext ,其parent为null,表明它是RootContext。 配置文件的对应关系 Spring MVC典型配置 RootContext配置 : ChildContext配置 : Bean扫描规则 在哪个配置文件中声明注解扫描标签,扫描到的Bean就会被注册到对应的上下文中: 总结对比 相同点 ServletContext都是 ApplicationContextFacade 对象 作用范围都是ServletContext最大,其他Context都是它的属性 不同点 | 特性 | Spring MVC | Spring Boot | |------|-----------|-------------| | 上下文数量 | 多个(1个Root + n个Child) | 单一RootContext | | Bean存储 | 分散在不同上下文中 | 全部存储在单一上下文中 | | 获取方式 | 有多种获取特定上下文的方法 | 统一获取方式 | 实际应用意义 内存马注入 :通常选择获取ChildContext而非RootContext,因为ChildContext可以访问更多资源 Bean查找 :需要注意Bean名称的首字母小写规则 上下文隔离 :理解父子上下文关系有助于设计合理的应用结构 参考资源 Spring官方文档 CSDN相关文章 通过深入理解Spring的上下文机制,开发者可以更好地掌握框架的核心原理,为高级应用和问题排查打下坚实基础。