web.xml
1 | <!-- 省略非关键的配置 --> |
[1]
处配置了org.springframework.web.context.ContextLoaderListener
对象,它实现了javax.servlet.ServletContextListener
接口,会初始化一个Root WebApplicationContext容器;[2]
处配置了org.springframework.web.servlet.DispatcherServlet
对象,它实现了javax.servlet.http.HttpServlet
,除了拦截我们制定的*.do
请求外,也会初始化一个属于它的 Servlet WebApplicationContext 容器,并且这个容器是以 [1] 处的 Root 容器作为父容器。
下面就以上两个容器进行分析,一个是业务容器,一个是Web容器。
Root WebApplicationContext
Root WebApplicationContext也就是业务容器,用于加载业务逻辑相关的类,比如service、dao层的一些类。它的初始化是通过ContextLoaderListener
来实现,在Servlet容器启动时,例如Tomcat、Jetty启动,则会被ContextLoaderListener
监听到,从而调用contextInitialized(ServletContextEvent event)
方法,初始化Root WebApplicationContext容器。它的核心配置如下:
1 | <!-- [1] Spring配置 --> |
如上,ContextLoaderListener
可通过ServletContext
获取到contextConfigLocation
配置。这样,业务容器就可以加载application.xml
配置文件了。
ContextLoaderListener
org.springframework.web.context.ContextLoaderListener
,实现ServletContextListener
接口,继承ContextLoader
类,上面说过,它实现了Servlet容器启动和关闭时,分别初始化和销毁WebApplicationContext
容器。
对于ContextLoaderListener
,它的初始化和销毁的真正逻辑其实是由父类ContextLoader
实现的。
初始化
WebApplicationContext
容器:1
2
3
4
5
6
7// ContextLoaderListener.java
public void contextInitialized(ServletContextEvent event) {
// 初始化 WebApplicationContext,调用父类实现的方法
initWebApplicationContext(event.getServletContext());
}销毁
WebApplicationContext
容器:1
2
3
4
5
6
7// ContextLoaderListener.java
public void contextDestroyed(ServletContextEvent event) {
closeWebApplicationContext(event.getServletContext());
ContextCleanupListener.cleanupAttributes(event.getServletContext());
}
Servlet WebApplicationContext
Servlet WebApplicationContext也就是Web容器,它的初始化是在DispatcherServlet
初始化的过程中执行,并且会将业务容器作为父容器,之所以这样是因为Web容器中的一些Bean会依赖于业务容器中的Bean,比如我们的controller层接口通常会依赖service层的业务逻辑类。
以下是这个继承体系中各个类负责的任务,结构还是比较清晰的:
HttpServletBean
:覆写了父类HttpServlet
中的init()
方法,是创建Web容器的入口,负责将ServletConfig
设置到HttpServletBean
的子类对象中(比如DispatcherServlet
)。类上的简单注释如下:1
2
3
4
5
6
7// HttpServletBean.java
/**
* Simple extension of {@link javax.servlet.http.HttpServlet} which treats
* its config parameters ({@code init-param} entries within the
* {@code servlet} tag in {@code web.xml}) as bean properties.
*/FrameworkServlet
:覆写了父类HttpServletBean
中的initServletBean()
方法,负责初始化Servlet WebApplicationContext容器。类上的简单注释如下:1
2
3
4
5
6// FrameworkServlet.java
/**
* Base servlet for Spring's web framework. Provides integration with
* a Spring application context, in a JavaBean-based overall solution.
*/DispatcherServlet
:负责初始化Spring MVC的各个组件,以及处理客户端的请求。类上的简单注释如下:1
2
3
4
5
6
7// DispatcherServlet.java
/**
* Central dispatcher for HTTP request handlers/controllers, e.g. for web UI controllers
* or HTTP-based remote service exporters. Dispatches to registered handlers for processing
* a web request, providing convenient mapping and exception handling facilities.
*/