在 WEB 开发中,可能会很少需要显示的获得 ApplicationContext 来得到由 Spring 进行管理的某些 Bean, 今天我就遇到了,在这里和大家分享一下, WEB 开发中,怎么获取 ApplicationContext
一 要想怎么获取 ApplicationContext, 首先必须明白 Spring 内部 ApplicationContext 是怎样存储的。下面我们来跟踪一下源码
首先:从大家最熟悉的地方开始
- <listener>
- <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
- </listener>
上面这一段,大家很熟悉吧。好,让我们看一看它到底实现了些啥。
- public class ContextLoaderListener<span style="color: #ff0000;"> <span style="color: #000000;">implements ServletContextListener</span></span> {
- private ContextLoader contextLoader;
- /**
- * Initialize the root web application context.
- */
- public void <span style="color: #000000;">contextInitialized</span>(ServletContextEvent event) {
- this.contextLoader = createContextLoader();
- this.contextLoader.<span style="color: #000000;">initWebApplicationContext</span>(event.getServletContext());
- }//下面的略
显然,ContextLoaderListener实现了ServeletContextListenet,在ServletContext初始化的时候,会进行Spring的初始化,大家肯定会想,Spring的初始化应该与ServletContext有一定关系吧?有关系吗?接下来让我们进入
ContextLoader.initWebApplicationContext方法
- public WebApplicationContext initWebApplicationContext(ServletContext servletContext)
- throws IllegalStateException, BeansException {
- //从ServletContext中查找,是否存在以<span style="color: #000000;">WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE为Key的值</span>
- 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!");
- }
- try {
- // Determine parent for root web application context, if any.
- ApplicationContext parent = loadParentContext(servletContext);
- // it is available on ServletContext shutdown.
- this.context = createWebApplicationContext(servletContext, parent);
- //将ApplicationContext放入ServletContext中,其key为<span style="color: #000000;">WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE</span>
- servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, this.context);
- //将ApplicationContext放入ContextLoader的全局静态常量Map中,其中key为:<span style="color: #000000;">Thread.currentThread().getContextClassLoader()即当前线程类加载器</span>
- currentContextPerThread.put(Thread.currentThread().getContextClassLoader(), this.context);
- return this.context;
- }
从上面的代码大家应该明白了Spring初始化之后,将ApplicationContext存到在了两个地方,那么是不是意味着我们可以通过两种方式取得ApplicationContext?
第一种获取方式:
注意:WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE = WebApplicationContext.class.getName() + ".ROOT";
即为 "org.springframework.web.context.WebApplicationContext.ROOT"
那么咱们是不是可以这样获得ApplicationContext:
- request.getSession().getServletContext().getAttribute("org.springframework.web.context.WebApplicationContext.ROOT")
确实可以,而且我们想到这种方法的时候,Spring早就提供给我们接口了:
- public abstract class WebApplicationContextUtils {
- public static WebApplicationContext getRequiredWebApplicationContext(ServletContext sc)
- throws IllegalStateException {
- WebApplicationContext wac = getWebApplicationContext(sc);
- if (wac == null) {
- throw new IllegalStateException("No WebApplicationContext found: no ContextLoaderListener registered?");
- }
- return wac;
- }
getWebApplicationContext方法如下:
- public static WebApplicationContext getWebApplicationContext(ServletContext sc) {
- return getWebApplicationContext(sc, WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE);
- }
哈哈,明白了吧,它和我们自己实现的方法是一样的。
这种方法一般用在你自己定义了一个Listener并且实现了ServletContextListener接口,在web.xml中你需要把这个Listener配置好
<!--
用于做初始化工作的监听器,一定要配置到Spring的ContextLoaderListener之后,因为要用到Spring的容器对象
-->
<listener>
<listener-class>cn.itcast.oa.Utils.InitListener</listener-class>
</listener>
实现这个监听器的类如下:
public class InitListener implements ServletContextListener {
//启动时,为最大的作用于初始化
public void contextInitialized(ServletContextEvent sce) {
// 获取容器与相关的Service对象
ApplicationContext ac = WebApplicationContextUtils.getWebApplicationContext(sce.getServletContext());
PrivilegeService privilegeService = (PrivilegeService) ac.getBean("privilegeServiceImpl");
// 准备数据:topPrivilegeList
List<Privilege> topPrivilegeList = privilegeService.findTopList();
sce.getServletContext().setAttribute("topPrivilegeList", topPrivilegeList);
System.out.println("------------> 已准备数据 <------------");
}
public void contextDestroyed(ServletContextEvent arg0) {
}
}
还有一种简单的
代码:
ApplicationContext ac = new FileSystemXmlApplicationContext("applicationContext.xml");
ac.getBean("beanId");
说明:这种方式适用于采用Spring框架的独立应用程序,需要程序通过配置文件手工初始化Spring的情况。
然后。。。。。获取的这个ApplicationContext对象后你就可以getBean()了。。。。。啦啦
参考 http://www.blogjava.net/Todd/archive/2010/04/22/295112.html