ContextLoaderListener

来源:互联网 发布:js的单例模式 编辑:程序博客网 时间:2024/05/17 23:54

 

ContextLoaderListener继承ServletContextListener类,实现contextInitialized方法

public void contextInitialized(ServletContextEvent event) {
  this.contextLoader = createContextLoader();
  this.contextLoader.initWebApplicationContext(event.getServletContext());
 }

创建contextLoader,调用initWebApplicationContext方法:

// Determine parent for root web application context, if any.
   ApplicationContext parent = loadParentContext(servletContext);

   // Store context in local instance variable, to guarantee that
   // it is available on ServletContext shutdown.
   this.context = createWebApplicationContext(servletContext, parent);

//createWebApplicationContext方法还回默认的XmlWebApplicationContext
   servletContext.setAttribute(
     WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, this.context);
//并放入ServletContext中

跟踪到createWebApplicationContext(),

Class contextClass = determineContextClass(servletContext);
  //Return the WebApplicationContext implementation class to use, 
  //either the default XmlWebApplicationContext or a custom context class if specified
  if (!ConfigurableWebApplicationContext.class.isAssignableFrom(contextClass)) {
   throw new ApplicationContextException("Custom context class [" + contextClass.getName() +
     "] is not of type [" + ConfigurableWebApplicationContext.class.getName() + "]");
  }

  ConfigurableWebApplicationContext wac =
    (ConfigurableWebApplicationContext) BeanUtils.instantiateClass(contextClass);
  //  BeanUtils.instantiateClass is Convenience method to instantiate a class using its no-arg constructor
  wac.setParent(parent);
  wac.setServletContext(servletContext);
  String configLocation = servletContext.getInitParameter(CONFIG_LOCATION_PARAM);
  //configLocation = /WEB-INF/applicationContext.xml;
  if (configLocation != null) {
   wac.setConfigLocations(StringUtils.tokenizeToStringArray(configLocation,
     ConfigurableWebApplicationContext.CONFIG_LOCATION_DELIMITERS));
   //Set the config locations for this web application context. 
   //If not set, the implementation is supposed to use a default 
   //for the given namespace or the root web application context, as appropriate. 
  }

  wac.refresh();
  return wac;
 最后返回XmlWebApplicationContext实例;

1) org.springframework.web.context.ContextLoaderListener 这个类被定义为监听器,并读取在参数contextConfigLocation中定义的xml 文件,如果不设置contextConfigLocation的初始参数则默认会读取    WEB-INF路径下的 application.xml文件,如果需要自定义了另外的xml 则可以在contextConfigLocation下定义,ContextLoaderListener会读取这些XML文件并产生 WebApplicationContext对象,然后将这个对象放置在ServletContext的属性里,这样我们只要可以得到Servlet就可以得到WebApplicationContext对象,并利用这个对象访问spring 容器管理的bean。
    (2)解析ContextLoadListener的源代码

// 实现了servlet的ServletContextListener接口

public class ContextLoaderListener
     implements ServletContextListener
{
private ContextLoader contextLoader;

// 这个是最重要的,利用contextLoader 来完成所有的工作
public void contextInitialized(ServletContextEvent event)
{
    this.contextLoader = createContextLoader();
    this.contextLoader.initWebApplicationContext(event.getServletContext());
}

protected ContextLoader createContextLoader()
{
    return new ContextLoader();
}

public ContextLoader getContextLoader()
{
    return this.contextLoader;
}

public void contextDestroyed(ServletContextEvent event)
{
    if (this.contextLoader != null)
      this.contextLoader.closeWebApplicationContext(event.getServletContext());
}
}

下面看一下ContextLoader .initWebApplicationContext方法

public WebApplicationContext initWebApplicationContext(ServletContext servletContext)
    throws IllegalStateException, BeansException
{
    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!");
    }

    long startTime = System.currentTimeMillis();
    if (this.logger.isInfoEnabled())
      this.logger.info("Root WebApplicationContext: initialization started");

    servletContext.log("Loading Spring root WebApplicationContext");
    try
    {
      ApplicationContext parent = loadParentContext(servletContext);
      
      // 这里得到WebApplicationContext对象 ,下面具体看一下这个方法是如何实现的
      this.context = createWebApplicationContext(servletContext, parent);
      
    // 将这个对象设置到servletContext的属性里
      servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, this.context);

      if (this.logger.isInfoEnabled()) {
          this.logger.info("Using context class [" + this.context.getClass().getName() + "] for root WebApplicationContext");
      }

      if (this.logger.isDebugEnabled()) {
        this.logger.debug("Published root WebApplicationContext [" + this.context + "] as ServletContext attribute with name [" + WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE + "]");
      }

      if (this.logger.isInfoEnabled()) {
        long elapsedTime = System.currentTimeMillis() - startTime;
        this.logger.info("Root WebApplicationContext: initialization completed in " + elapsedTime + " ms");
      }

      return this.context;
    }

protected WebApplicationContext createWebApplicationContext(ServletContext servletContext, ApplicationContext parent)
    throws BeansException
{
    // 返回在web.xml 中参数contextClass自定义类对应的对象这个类,这个类实现了XmlWebApplicationContext
    // XmlWebApplicationContext继承了AbstractRefreshableWebApplicationContext类中定义的方法protected String[] getConfigLocations() ,这个方法默认可以加载contextConfigLocation中定义的xml 文件,如果你重写了这个方法还可以在任意地方加载你想要的xml文件。

    Class contextClass = determineContextClass(servletContext);
    if (!(ConfigurableWebApplicationContext.class.isAssignableFrom(contextClass))) {
      throw new ApplicationContextException("Custom context class [" + contextClass.getName() + "] is not of type   ConfigurableWebApplicationContext");
    }
    
   // 得到 WebApplicationContext 
    ConfigurableWebApplicationContext wac = (ConfigurableWebApplicationContext)BeanUtils.instantiateClass(contextClass);

    wac.setParent(parent);
    wac.setServletContext(servletContext);
    String configLocation = servletContext.getInitParameter("contextConfigLocation");
    if (configLocation != null) {
      wac.setConfigLocations(StringUtils.tokenizeToStringArray(configLocation, ",; \t\n"));
    }

    wac.refresh();
    return wac;
}
原创粉丝点击