前言:经过实例结合源码的方式解读,其中涉及到的文件来自于博主的Github毕设项目wxServer
Note: Springboot应用不在本文章讨论范围java
在通常的web应用程序,咱们假若用到Spring的话,须要在web.xml中配置如下的信息来使一些容器,例如Tomcat
、Jetty
等来加载Springgit
<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
类在应用启动时加载其服务github
查看某个类的重要功能最好是观察其的注释,ContextLoaderLinstener
官方注释以下:web
//父级启动类,可用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
节点具备代码逻辑上的先写先加载的特色。spring
特别须要注意的是若是用户须要用到
Log4jConfigListener
的话,则必须写在ContextLoaderListener
的前面app
public class ContextLoaderListener extends ContextLoader implements ServletContextListener{}
最应该关注的是ServletContextListenr
接口,咱们应该知道实现此接口的类会在应用启动的时候,自动的调用其接口方法contextInitialized(ServletContextEvent event)
;
在关闭应用时候则会调用其另一个接口方法contextDestroyed(ServletContextEvent evet)
用来关闭web上下文信息。spa
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); } } } }
web.xml中的listener节点具备先写先加载的特色,相似于java代码中的顺序执行code
Log4jConfigListener类加载必须在ContextLoaderListenr类以前xml
ContextLoaderListener启动Spring并生成Spring根web服务上下文则是经过其父类ContextLoader来实现的,其销毁也只会销毁具备
org.springwork
前缀的属性接口ServletContext表明应用服务上下文,其能够读取
<context-param>
级别的参数,而ServletConfig/FilterConfig则会读取其相应servlet节点/filter节点
下的<init-param>
参数web.xml中listener、servlet、filter执行顺序为listener>filter>servlet,同类型的执行顺序为listener知足先写先加载,servlet、filter则由
mapping
节点的前后顺序加载
Spring源码情操陶冶-ContextLoader