怎么获取Spring的ApplicationContext(一)

2014-11-23 21:55:46 · 作者: · 浏览: 11

在 WEB 开发中,可能会很少需要显示的获得 ApplicationContext 来得到由 Spring 进行管理的某些 Bean, 今天我就遇到了,在这里和大家分享一下, WEB 开发中,怎么获取 ApplicationContext

一 要想怎么获取 ApplicationContext, 首先必须明白 Spring 内部 ApplicationContext 是怎样存储的。下面我们来跟踪一下源码

首先:从大家最熟悉的地方开始

Java代码 收藏代码
  1. org.springframework.web.context.ContextLoaderListener
  2. 上面这一段,大家很熟悉吧。好,让我们看一看它到底实现了些啥。

    Java代码 收藏代码
    1. public class ContextLoaderListener implements ServletContextListener {
    2. private ContextLoader contextLoader;
    3. /**
    4. * Initialize the root web application context.
    5. */
    6. public void contextInitialized(ServletContextEvent event) {
    7. this.contextLoader = createContextLoader();
    8. this.contextLoader.initWebApplicationContext(event.getServletContext());
    9. }//下面的略


      显然,ContextLoaderListener实现了ServeletContextListenet,在ServletContext初始化的时候,会进行Spring的初始化,大家肯定会想,Spring的初始化应该与ServletContext有一定关系吧?有关系吗?接下来让我们进入

      ContextLoader.initWebApplicationContext方法

      Java代码 收藏代码
      1. public WebApplicationContext initWebApplicationContext(ServletContext servletContext)
      2. throws IllegalStateException, BeansException {
      3. //从ServletContext中查找,是否存在以WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE为Key的值 Java代码 收藏代码
        1. if (servletContext.getAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE) != null){
        2. throw new IllegalStateException(
        3. "Cannot initialize context because there is already a root application context present - " +
        4. "check whether you have multiple ContextLoader* definitions in your web.xml!");
        5. }
        6. try {
        7. // Determine parent for root web application context, if any.
        8. ApplicationContext parent = loadParentContext(servletContext);
        9. // it is available on ServletContext shutdown.
        10. this.context = createWebApplicationContext(servletContext, parent);
        11. //将ApplicationContext放入ServletContext中,其key为WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE Java代码 收藏代码
          1. servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, this.context);
          2. //将ApplicationContext放入ContextLoader的全局静态常量Map中,其中key为:Thread.currentThread().getContextClassLoader()即当前线程类加载器 Java代码 收藏代码
            1. currentContextPerThread.put(Thread.currentThread().getContextClassLoader(), this.context);
            2. return this.context;
            3. }

              从上面的代码大家应该明白了Spring初始化之后,将ApplicationContext存到在了两个地方,那么是不是意味着我们可以通过两种方式取得ApplicationContext

              第一种获取方式:


              注意:WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE = WebApplicationContext.class.getName() + ".ROOT";

              即为 "org.springframework.web.context.WebApplicationContext.ROOT"

              那么咱们是不是可以这样获得ApplicationContext:

              Java代码 收藏代码
              1. request.getSession().getServletContext().getAttribute("org.springframework.web.context.WebApplicationContext.ROOT")

                确实可以,而且我们想到这种方法的时候,Spring早就提供给我们接口了:

                Java代码 收藏代码
                1. public abstract class WebApplicationContextUtils {
                2. public static WebApplicationContext getRequiredWebApplicationContext(ServletContext sc)
                3. throws IllegalStateException {
                4. WebApplicationContext wac = getWebApplicationContext(sc);
                5. if (wac == null) {
                6. throw new IllegalStateException("No WebApplicationContext found: no ContextLoaderListener registered ");
                7. }
                8. return wac;
                9. }

                  getWebApplicationContext方法如下:

                  Java代码 收藏代码
                  1. public static WebApplicationContext getWebApplicationContext(ServletContext sc) {
                  2. return getWebApplicationContext(sc, WebApplicationContext.ROO