zoukankan      html  css  js  c++  java
  • Spring源码情操陶冶-ContextLoaderListener

    前言:通过实例结合源码的方式解读,其中涉及到的文件来自于博主的Github毕设项目wxServer
    Note: Springboot应用不在本文章讨论范围

    web.xml中启用Spring

    在一般的web应用程序,我们倘若用到Spring的话,需要在web.xml中配置以下的信息来使一些容器,例如TomcatJetty等来加载Spring

      <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:com/du/wx/resources/spring/springContext.xml</param-value>
      </context-param>
      <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
      </listener>
    

    Spring主要通过ContextLoaderListener类在应用启动时加载其服务

    ContextLoaderListener的官方注释

    查看某个类的重要功能最好是观察其的注释,ContextLoaderLinstener官方注释如下:

      //父级启动类,可用ContextLoader启动和ContextCleanupListener来关闭Spring的根web应用上下文
      Bootstrap listener to start up and shut down Spring's root {@link WebApplicationContext}.
      Simply delegates to {@link ContextLoader} as well as to {@link ContextCleanupListener}.
     
      //这里给出了提示,如果需要用到自定义log4j的配置的话,则ContextListener需要在Log4jConfigListener之后
      <p>This listener should be registered after {@link org.springframework.web.util.Log4jConfigListener}
      in {@code web.xml}, if the latter is used.
     //从Spring3.1之后,注入根web应用上下文可通过 WebApplicationInitializer,容器在启动会加载此接口,但是有个要求是容器的Servlet版本必须是3.0+,对Tomcat来说必须是7.0.15版本以上
      <p>As of Spring 3.1, {@code ContextLoaderListener} supports injecting the root web
      application context via the {@link #ContextLoaderListener(WebApplicationContext)}
      constructor, allowing for programmatic configuration in Servlet 3.0+ environments.
      See {@link org.springframework.web.WebApplicationInitializer} for usage examples.
     
      @author Juergen Hoeller
      @author Chris Beams
      @since 17.02.2003
      @see #setContextInitializers
      @see org.springframework.web.WebApplicationInitializer
      @see org.springframework.web.util.Log4jConfigListener
    

    重要的批注都在新增的注释上,并且我们可以发现,web.xml中的listener节点具有代码逻辑上的先写先加载的特点。

    特别需要注意的是如果用户需要用到Log4jConfigListener的话,则必须写在ContextLoaderListener的前面

    ContextLoaderListener结构

    public class ContextLoaderListener extends ContextLoader implements ServletContextListener{}
    

    最应该关注的是ServletContextListenr接口,我们应该知道实现此接口的类会在应用启动的时候,自动的调用其接口方法contextInitialized(ServletContextEvent event);
    关闭应用时候则会调用其另外一个接口方法contextDestroyed(ServletContextEvent evet)用来关闭web上下文信息。

    • 初始化
      public void contextInitialized(ServletContextEvent event) {
      	//调用的是父类ContextLoader的方法,看出来这是启动的关键
      	initWebApplicationContext(event.getServletContext());
      }
      
    • 关闭
      	//与初始化相对
      	closeWebApplicationContext(event.getServletContext());
      	//使用ContextCleanupLister监听类来销毁ServletContext的springwork属性信息
      	ContextCleanupListener.cleanupAttributes(event.getServletContext());
      
      这里我们简单的看下销毁属性的代码方法
      Enumeration<String> attrNames = sc.getAttributeNames();
      	while (attrNames.hasMoreElements()) {
      		String attrName = attrNames.nextElement();
      		//筛选出专属spring的属性
      		if (attrName.startsWith("org.springframework.")) {
      			Object attrValue = sc.getAttribute(attrName);
      			//基本WebApplication都实现了DisposableBean接口,表明所有的Bean都是可以释放的
      			if (attrValue instanceof DisposableBean) {
      				try {
      					((DisposableBean) attrValue).destroy();
      				}
      				catch (Throwable ex) {
      					logger.error("Couldn't invoke destroy method of attribute with name '" + attrName + "'", ex);
      				}
      			}
      		}
      	}
      

    记录总结

    1. web.xml中的listener节点具有先写先加载的特点,类似于java代码中的顺序执行

    2. Log4jConfigListener类加载必须在ContextLoaderListenr类之前

    3. ContextLoaderListener启动Spring并生成Spring根web服务上下文则是通过其父类ContextLoader来实现的,其销毁也只会销毁具有org.springwork前缀的属性

    4. ServletContext代表应用服务上下文,其可以读取<context-param>级别的参数,而ServletConfig/FilterConfig则会读取其相应servlet节点/filter节点下的<init-param>参数

    5. web.xml中listener、servlet、filter执行顺序为listener>filter>servlet,同类型的执行顺序为listener满足先写先加载,servlet、filter则由mapping节点的先后顺序加载

    下节预告

    Spring源码情操陶冶-ContextLoader

  • 相关阅读:
    线段树优化dp(elect选择)
    gdb调试
    无参装饰器
    3.23作业
    3.22周末作业
    函数对象与闭包函数
    3.20作业
    3.19作业
    名称空间与作用域
    函数参数的使用
  • 原文地址:https://www.cnblogs.com/question-sky/p/6683345.html
Copyright © 2011-2022 走看看