web.xml中配置ContextLoaderListener的作用

ContextLoaderListener的配置

<listener>
  <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>

java web应用,在web.xml中经常能看到上述的配置,它的作用是什么呢?实例化spring的web容器。那么它究竟是怎么发挥作用的?
通过UML图发现,ContextLoaderListener实现了ServletContextListener接口。

public interface ServletContextListener extends EventListener {
    void contextInitialized(ServletContextEvent var1);

    void contextDestroyed(ServletContextEvent var1);
}

在web容器启动的时候,容器会调用**contextInitialized()**方法。

//ContextLoaderListener 实现了contextInitialized()方法,。
public void contextInitialized(ServletContextEvent event) {
   this.contextLoader = createContextLoader();
   if (this.contextLoader == null) {
      this.contextLoader = this;
   }
   //具体的实例化工作会委托ContextLoader处理
   this.contextLoader.initWebApplicationContext(event.getServletContext());
}

下面是initWebApplicationContext()方法的具体实现,为了简介好看,我省略一些异常处理的代码

public WebApplicationContext initWebApplicationContext(ServletContext servletContext) {
    // 检查servletContent上下文中是否已经实例化了
   if (servletContext.getAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE) != null) {
      throw new IllegalStateException("....")
   }
//Root WebApplicationContext: initialization started
   long startTime = System.currentTimeMillis();

   try {
      // Store context in local instance variable, to guarantee that
      // it is available on ServletContext shutdown.
      if (this.context == null) {
          //这里已经创建context容器,具体创建步骤见下一节createWebApplicationContex()分析
         this.context = createWebApplicationContext(servletContext);
      }
      //  这一段可以无视,不用管....
      if (this.context instanceof ConfigurableWebApplicationContext) {
         ConfigurableWebApplicationContext cwac = (ConfigurableWebApplicationContext) this.context;
         if (!cwac.isActive()) {
            // The context has not yet been refreshed -> provide services such as
            // setting the parent context, setting the application context id, etc
            if (cwac.getParent() == null) {
               // The context instance was injected without an explicit parent ->
               // determine parent for root web application context, if any.
               ApplicationContext parent = loadParentContext(servletContext);
               cwac.setParent(parent);
            }
            configureAndRefreshWebApplicationContext(cwac, servletContext);
         }
      }
      servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, this.context);

      ClassLoader ccl = Thread.currentThread().getContextClassLoader();
      if (ccl == ContextLoader.class.getClassLoader()) {
         currentContext = this.context;
      }
      else if (ccl != null) {
         currentContextPerThread.put(ccl, this.context);
      }
      return this.context;
   }
}

createWebApplicationContext()分析:

protected WebApplicationContext createWebApplicationContext(ServletContext sc) {
    ...
    // 核心方法决定要实例化的是哪一个类
   Class<?> contextClass = determineContextClass(sc);
   ....
}

determineContextClass(sc)分析:

protected Class<?> determineContextClass(ServletContext servletContext) {
    //大致思路: 
    //1、看有没有在web.xml中指定contextClass参数,如果有实例化该指定类名
   String contextClassName = servletContext.getInitParameter(CONTEXT_CLASS_PARAM);
   if (contextClassName != null) {
      try {
         return ClassUtils.forName(contextClassName, ClassUtils.getDefaultClassLoader());
      }
      catch (ClassNotFoundException ex) {
         throw new ApplicationContextException(
               "Failed to load custom context class [" + contextClassName + "]", ex);
      }
   }
   // 2、如果没有指定,通过默认的策略实例化。
   //默认的策略是去加载ContextLoader.properties文件里指定的class全类名
   //org.springframework.web.context.WebApplicationContext=
   //                                      org.springframework.web.context.support.XmlWebApplicationContext
   // 点开这个类 有没有发现很神奇的东西呢 是不是很熟悉,默认情况下 我们spring配置文件就是放在这里
   //public class XmlWebApplicationContext extends AbstractRefreshableWebApplicationContext {
   //public static final String DEFAULT_CONFIG_LOCATION = "/WEB-INF/applicationContext.xml";
   //public static final String DEFAULT_CONFIG_LOCATION_PREFIX = "/WEB-INF/";
   //public static final String DEFAULT_CONFIG_LOCATION_SUFFIX = ".xml";
   
   else {
      contextClassName = defaultStrategies.getProperty(WebApplicationContext.class.getName());
      try {
         return ClassUtils.forName(contextClassName, ContextLoader.class.getClassLoader());
      }
      catch (ClassNotFoundException ex) {
         throw new ApplicationContextException(
               "Failed to load default context class [" + contextClassName + "]", ex);
      }
   }
}
  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值