ContextLoaderListener

(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;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值