当我们开始使用Spring Framework时,能想到的最基本的问题是:ApplicationContext在spring中扮演什么的角色,它和WebApplicationContext有什么不同呢。在考虑这些之前,应该先知道What is a Context in Java
1.What is a Context in Java
A context可以被说成是被提供给当前工作单元的正运行的环境,它可以是环境变量、实例变量、类的状态等等。当我这么说的时候,我的意思是ServletContext 表示在它的容器内的servlet环境,与ApplicationContext 类似。而ApplicationContext 表示在spring容器内的Spring application’s核心环境。
所以类似的那有Servlet’s ServletContext, JSF’s FacesContext, Spring’s ApplicationContext, Android’s Context, JNDI’s InitialContext,这些context都遵循Facade Pattern去抽象这个环境的具体细节给终端用户,具体抽象的思想和做法是提供接口用于同终端用户交流沟通
2. Spring Context Configuration
In Spring web applications,有两个context会在服务开始的时候被初始化。他们中每个被不同地配置和初始化。一个是Application Context,另一个是Web Application Context。
2.1 ApplicationContext
Application Context 被一个ContextLoaderListener or ContextLoaderServlet初始化,我们定义ContextLoaderListener or ContextLoaderServlet在我们应用的web.xml文件中并像下面展示的那样配置:
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/root-context.xml</param-value>
</context-param>
在上述配置中,我们正在请spring去加载root-context.xml并从它创建一个Application Context,如果contextConfigLocation在上面代码片段中没有提到,它默认查找/WEB-INF/applicationContext.xml。就像下面这样:
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
- [ ] 注意:There will be always be one application context per web application.
2.2 WebApplicationContext
WebApplicationContext是一个servlet-specific context ,它被配置在应用的web.xml*文件中的dispatcher servlets所加载,所以每个dispatcher servlet有它自己的从-servlet.xml文件初始化的servlet-context。这允许我们根据 the incoming requests based on the servlet’s url-pattern and handle them。这样的话,dispatcher servlets中的一个能通过Controller服务web页面,而另一个能被用于实现无状态的REST web service。综上,我们的理解是:一个web应用能有多个dispatcher-servlet configurations,因此也就有多个web-application contexts.
Web Application context extended Application Context which is designed to work with the standard javax.servlet.ServletContext so it’s able to communicate with the container.
public interface WebApplicationContext extends ApplicationContext {
ServletContext getServletContext();
}
Beans, instantiated in WebApplicationContext will also be able to use ServletContext if they implement ServletContextAware interface
package org.springframework.web.context;
public interface ServletContextAware extends Aware {
void setServletContext(ServletContext servletContext);
}
如果我们想改变dispatcher-servlet文件的名字或改变他的位置,我们可以增加 init-param with contextConfigLocation as param-name,像下面代码:
<servlet>
<servlet-name>mvc-dispatcher</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/sample-dispatcher-servlet.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>mvc-dispatcher</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
正如上述代码片段,spring没有发现名字为mvc-dispatcher-servlet.xml的dispatcher-servlet context文件,但是代替的它将为contextConfigLocation查找init-param属性指定的值,如:sample-dispatcher-servlet.xml
2.3 Difference between the two contexts
文章最重要的部分是what’s the difference between the two contexts。
首先,正如上面已经提到的,ApplicationContext is the root-context,它有一些bean的配置,这些配置是我们可能想在整个应用中作为单例使用的(use/re-use)。在web应用中总会有且只有一个application context。然而,可以有多个WebApplicationContexts给我们指定在应用的web.xml中的每个dispatcher servlet。
- [ ] 注意:WebApplicationContext internally extends ApplicationContext, and as a child inherits all the beans from its parent. So we can also override the parent bean within our WebApplicationContext.
在服务中间件(如业务逻辑组件service、数据访问组件DAO,我们更应该在ApplicationContext XML定义他们)和web关联的组件(如controllers 和view-resolvers,我们更应该定义他们在各自的 dispatcher-servlet‘s WebApplicationContext)之间保持一个清晰的分离那是比较好的
[ ] 注意:At server startup, ContextLoaderListener instantiates beans defined in applicationContext.xml. After the completion of bean instantiation defined in applicationContext.xml then beans defined in springweb-servlet.xml are instantiated.
So instantiation order is root is application context, then DispatcherServlet.[ ] 注意:Configuring contextLoaderListener is completely optional. We can boot up a Spring application with just the dispatcher-servlet, without even configuring contextLoaderListener (that loads up the root-context).
原文:
http://www.jcombat.com/spring/applicationcontext-webapplicationcontext
参考:
1. http://stackoverflow.com/questions/3652090/difference-between-applicationcontext-xml-and-spring-servlet-xml-in-spring-frame
2. https://www.quora.com/What-is-the-difference-between-WebApplicationContext-and-ApplicationContext-Why-do-we-use-ContextLoaderListener-and-what-is-Listener-exactly-in-Spring
3. http://javarevisited.blogspot.com/2012/11/difference-between-beanfactory-vs-applicationcontext-spring-framework.html