ApplicationContext 是 BeanFactory 接口的子接口,它增强了 BeanFactory 的功能,处于 context 包下。很多时候, ApplicationContext 允许以声明式方式操作容器,
无须手动创建。可利用如 ContextLoader 的支持类,在 Web 应用启动时自动创建 ApplicationContext。当然,也可以采用编程方式创建 ApplicationContext。
ApplicationContext包括BeanFactory的全部功能,因此建议优先使用ApplicationContext。除非对于某些内存非常关键的应用,才考虑使用 BeanFactory。
spring为ApplicationContext提供的3种实现分别为:
1、 ClassPathXmlApplicationContext:利用类路径的XML文件来载入Bean定义的信息
[1] ApplicationContext ctx = new ClassPathXmlApplicationContext("bean.xml");
[2] String[] locations = {"bean1.xml", "bean2.xml", "bean3.xml"};
ApplicationContext ctx = new ClassPathXmlApplication(locations);
2、 FileSystemXmlApplicationContext:利用文件系统中的XMl文件来载入Bean
定义的信息
[1] ApplicationContext ctx = new FileSystemXmlApplicationContext("bean.xml"); //加载单个配置文件
[2] String[] locations = {"bean1.xml", "bean2.xml", "bean3.xml"};
ApplicationContext ctx = new FileSystemXmlApplicationContext(locations );//加载多个配置文件
[3] ApplicationContext ctx =new FileSystemXmlApplicationContext("D:/project/bean.xml");//根据具体路径加载
3、XmlWebApplicationContext:从Web系统中的XML文件来载入Bean定义的信息。
ServletContext servletContext = request.getSession().getServletContext();
ApplicationContext ctx = WebApplicationContextUtils.getWebApplicationContext(servletContext);
4.与BeanFactory通常以编程的方式被创建不同的是,ApplicationContext能以声明的方式创建,如使用ContextLoader。
当然你也可以使用ApplicationContext的实现之一来以编程的方式创建ApplicationContext实例。首先,让我们先分析ContextLoader接口及其实现。
ContextLoader接口有两个实现:ContextLoaderListener和ContextLoaderServlet。两者都实现同样的功能,但不同的是,
ContextLoaderListener不能在与Servlet 2.2兼容的web容器中使用。根据Servlet 2.4规范, servlet context listener要在web应用程序的servlet context建立后立即执行,
并要能够响应第一个请求(在servlet context要关闭时也一样):这样一个servlet context listener是初始化spring ApplicationContext的理想场所。
虽然使用哪个完全取决于你,但是在同等条件下应该首选ContextLoaderListener;对于更多兼容性的信息,请查看ContextLoaderServlet的JavaDoc。
5.配置WebApplicationContext的两种方法:
(1)利用Listener接口来实现
<listener>
<listener-class>
org.springframework.web.context.ContextLoaderListener
</listener-class>
</listener>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:applicationContext</param-value>
</context-param>
(2)利用Servlet接口来实现
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:applicationContext</param-value>
</context-param>
<Servlet>
<servlet-name>context</servlet-name>
<servlet-class>
org.springframework.web.context.ContextLoaderServlet
</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath*:/spring/config/applicationContextMVC.xml</param-value>
</init-param>
</servlet>
监听器首先检查contextConfigLocation参数,如果它不存在,它将使用/WEB-INF/applicationContext.xml作为默认值。
如果已存在,它将使用分隔符(逗号、冒号或空格)将字符串分解成应用上下文将位置路径。
ContextLoaderServlet同ContextLoaderListener一样使用'contextConfigLocation'参数。
6.listener和Servlet区别:
ContextLoaderListener中加载的context成功后,spring 将 applicationContext存放在ServletContext中key值为"org.springframework.web.context.WebApplicationContext.ROOT"的attribute中。
(servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, this.context));
可以通过WebApplicationContextUtils.getRequiredWebApplicationContext(servletContext)或
WebApplicationContextUtils.getWebApplicationContext(servletContext)方法来获取对应的applicationContext。
DispatcherServlet加载的context成功后,如果 publishContext属性的值设置为true的话(缺省为true) 会将applicationContext
存放在org.springframework.web.servlet.FrameworkServlet.CONTEXT. + (servletName)的attribute中。
则对应的applicationContext的attribute key值为org.springframework.web.servlet.FrameworkServlet.CONTEXT.mvcServlet。
在每次request请求时,DispatcherServlet会将此applicationContext存放在request中attribute值为 org.springframework.web.servlet.DispatcherServlet.CONTEXT中(request.setAttribute(WEB_APPLICATION_CONTEXT_ATTRIBUTE,getWebApplicationContext());)。
可以通过 RequestContextUtils.getWebApplicationContext 或 WebApplicationContextUtils.getWebApplicationContext(servletContext,attrname)方法 来获取对应的applicationContext。
从上面的分析可以看出,DispatcherServlet所加载的applicationContext可以认为是mvc私有的context,由于保存在servletContext中的key值与
通过ContextLoaderListener加载进来的applicationContext使用的key值不相同,因此如果只使用DispatcherServlet加载context的话,
如果程序中有地方使用WebApplicationContextUtils.getRequiredWebApplicationContext(servletContext) 来试图获取applicationContext时,
就会抛出"No WebApplicationContext found: no ContextLoaderListener registered?"的exception。