Spring MVC源码——Servlet WebApplicationContext
在使用Spring MVC进行Web开发时,Servlet WebApplicationContext 是一个核心概念。它是Spring MVC应用中管理Bean的容器,负责在Web环境下加载和管理Spring的Bean。理解 Servlet WebApplicationContext 的源码有助于我们更深入地掌握Spring MVC的工作原理,优化我们的应用程序。本文将深入剖析 Servlet WebApplicationContext 的源码,带你了解其内部机制。
目录#
- 什么是Servlet WebApplicationContext
- 源码结构和继承关系
- 初始化过程
- 核心方法解析
- 常见实践和最佳实践
- 示例用法
- 总结
- 参考资料
1. 什么是Servlet WebApplicationContext#
Servlet WebApplicationContext 是Spring框架为Web应用专门设计的 ApplicationContext 实现。它继承自 WebApplicationContext,在普通 ApplicationContext 的基础上,增加了对Web环境的支持。Servlet WebApplicationContext 可以与Servlet容器集成,在Servlet上下文中管理Spring的Bean,使得Spring的Bean可以在Web应用中方便地使用。
2. 源码结构和继承关系#
继承关系#
Servlet WebApplicationContext 继承自 WebApplicationContext,而 WebApplicationContext 又继承自 ApplicationContext。以下是简化的继承关系图:
ApplicationContext
└── WebApplicationContext
└── ServletWebApplicationContext主要实现类#
ServletWebApplicationContext 有多个实现类,其中最常用的是 XmlWebApplicationContext 和 AnnotationConfigWebApplicationContext。
XmlWebApplicationContext:通过XML配置文件来加载Bean定义。AnnotationConfigWebApplicationContext:通过Java注解来加载Bean定义。
3. 初始化过程#
Servlet WebApplicationContext 的初始化过程通常在Servlet容器启动时进行。以下是初始化的主要步骤:
3.1 配置上下文参数#
在 web.xml 中配置 ContextLoaderListener 和 contextConfigLocation 参数,指定Spring配置文件的位置。
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/applicationContext.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener>
</listener>3.2 启动 ContextLoaderListener#
ContextLoaderListener 是一个Servlet监听器,在Servlet容器启动时会触发 contextInitialized 方法。
public class ContextLoaderListener extends ContextLoader implements ServletContextListener {
@Override
public void contextInitialized(ServletContextEvent event) {
initWebApplicationContext(event.getServletContext());
}
@Override
public void contextDestroyed(ServletContextEvent event) {
closeWebApplicationContext(event.getServletContext());
}
}3.3 创建 Servlet WebApplicationContext#
在 initWebApplicationContext 方法中,会创建 Servlet WebApplicationContext 实例,并加载配置文件。
public WebApplicationContext initWebApplicationContext(ServletContext servletContext) {
if (servletContext.getAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE) != null) {
throw new IllegalStateException("Cannot initialize context because there is already a root application context present - " +
"check whether you have multiple ContextLoader* definitions in your web.xml!");
}
WebApplicationContext rootContext = createWebApplicationContext(servletContext);
servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, rootContext);
return rootContext;
}4. 核心方法解析#
4.1 getServletContext()#
该方法用于获取当前的 ServletContext 对象。
public ServletContext getServletContext() {
return this.servletContext;
}4.2 getServletConfig()#
该方法用于获取当前的 ServletConfig 对象。
public ServletConfig getServletConfig() {
return this.servletConfig;
}4.3 getNamespace()#
该方法用于获取当前 Servlet WebApplicationContext 的命名空间。
public String getNamespace() {
return this.namespace;
}5. 常见实践和最佳实践#
5.1 配置文件管理#
- 使用
contextConfigLocation参数指定多个配置文件,将不同功能的配置分开管理。
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/applicationContext.xml,/WEB-INF/securityContext.xml</param-value>
</context-param>5.2 使用注解配置#
推荐使用 AnnotationConfigWebApplicationContext 代替 XmlWebApplicationContext,通过Java注解来配置Bean。
public class AppInitializer implements WebApplicationInitializer {
@Override
public void onStartup(ServletContext servletContext) throws ServletException {
AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext();
context.register(AppConfig.class);
ServletRegistration.Dynamic dispatcher = servletContext.addServlet("dispatcher", new DispatcherServlet(context));
dispatcher.setLoadOnStartup(1);
dispatcher.addMapping("/");
}
}6. 示例用法#
以下是一个简单的Spring MVC应用示例,使用 AnnotationConfigWebApplicationContext 配置。
6.1 创建配置类#
@Configuration
@ComponentScan(basePackages = "com.example")
public class AppConfig {
// 配置Bean
}6.2 创建控制器#
@Controller
public class HelloController {
@RequestMapping("/hello")
@ResponseBody
public String hello() {
return "Hello, Spring MVC!";
}
}6.3 启动应用#
public class AppInitializer implements WebApplicationInitializer {
@Override
public void onStartup(ServletContext servletContext) throws ServletException {
AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext();
context.register(AppConfig.class);
ServletRegistration.Dynamic dispatcher = servletContext.addServlet("dispatcher", new DispatcherServlet(context));
dispatcher.setLoadOnStartup(1);
dispatcher.addMapping("/");
}
}7. 总结#
通过对 Servlet WebApplicationContext 源码的分析,我们了解了它在Spring MVC应用中的重要作用和工作原理。Servlet WebApplicationContext 作为Spring MVC的核心容器,负责加载和管理Bean,与Servlet容器紧密集成。在实际开发中,我们可以根据不同的需求选择合适的配置方式,优化应用程序的性能和可维护性。
8. 参考资料#
- Spring Framework Documentation
- Spring MVC官方文档
- 《Spring实战》(第5版)