Spring之WebContext不使用web.xml启动 初始化重要的类源码分析(Servlet3.0以上的)
入口:
org.springframework.web.SpringServletContainerInitializer implements ServletContainerInitializer
org.springframework.web.WebApplicationInitializer
ServletContainerInitializer这个类是Servlet3.0新增的接口,源码定义如下:
package javax.servlet; import java.util.Set; /**
* ServletContainerInitializers (SCIs) are registered via an entry in the
* file META-INF/services/javax.servlet.ServletContainerInitializer that must be
* included in the JAR file that contains the SCI implementation.
* <p>
* SCI processing is performed regardless of the setting of metadata-complete.
* SCI processing can be controlled per JAR file via fragment ordering. If an
* absolute ordering is defined, the only those JARs included in the ordering
* will be processed for SCIs. To disable SCI processing completely, an empty
* absolute ordering may be defined.
* <p>
* SCIs register an interest in annotations (class, method or field) and/or
* types via the {@link javax.servlet.annotation.HandlesTypes} annotation which
* is added to the class.
*
* @since Servlet 3.0
*/
public interface ServletContainerInitializer { /**
* Receives notification during startup of a web application of the classes
* within the web application that matched the criteria defined via the
* {@link javax.servlet.annotation.HandlesTypes} annotation.
*
* @param c The (possibly null) set of classes that met the specified
* criteria
* @param ctx The ServletContext of the web application in which the
* classes were discovered
*
* @throws ServletException If an error occurs
*/
void onStartup(Set<Class<?>> c, ServletContext ctx) throws ServletException;
}
而SpringServletContainerInitializer实现了这个接口,源码也很简单的只有几行,这里原封不动的将注释也拷过来,便于读懂注释分析:
/**
* Servlet 3.0 {@link ServletContainerInitializer} designed to support code-based
* configuration of the servlet container using Spring's {@link WebApplicationInitializer}
* SPI as opposed to (or possibly in combination with) the traditional
* {@code web.xml}-based approach.
*
* <h2>Mechanism of Operation</h2>
* This class will be loaded and instantiated and have its {@link #onStartup}
* method invoked by any Servlet 3.0-compliant container during container startup assuming
* that the {@code spring-web} module JAR is present on the classpath. This occurs through
* the JAR Services API {@link ServiceLoader#load(Class)} method detecting the
* {@code spring-web} module's {@code META-INF/services/javax.servlet.ServletContainerInitializer}
* service provider configuration file. See the
* <a href="http://download.oracle.com/javase/6/docs/technotes/guides/jar/jar.html#Service%20Provider">
* JAR Services API documentation</a> as well as section <em>8.2.4</em> of the Servlet 3.0
* Final Draft specification for complete details.
*
* <h3>In combination with {@code web.xml}</h3>
* A web application can choose to limit the amount of classpath scanning the Servlet
* container does at startup either through the {@code metadata-complete} attribute in
* {@code web.xml}, which controls scanning for Servlet annotations or through an
* {@code <absolute-ordering>} element also in {@code web.xml}, which controls which
* web fragments (i.e. jars) are allowed to perform a {@code ServletContainerInitializer}
* scan. When using this feature, the {@link SpringServletContainerInitializer}
* can be enabled by adding "spring_web" to the list of named web fragments in
* {@code web.xml} as follows:
*
* <pre class="code">
* {@code
* <absolute-ordering>
* <name>some_web_fragment</name>
* <name>spring_web</name>
* </absolute-ordering>
* }</pre>
*
* <h2>Relationship to Spring's {@code WebApplicationInitializer}</h2>
* Spring's {@code WebApplicationInitializer} SPI consists of just one method:
* {@link WebApplicationInitializer#onStartup(ServletContext)}. The signature is intentionally
* quite similar to {@link ServletContainerInitializer#onStartup(Set, ServletContext)}:
* simply put, {@code SpringServletContainerInitializer} is responsible for instantiating
* and delegating the {@code ServletContext} to any user-defined
* {@code WebApplicationInitializer} implementations. It is then the responsibility of
* each {@code WebApplicationInitializer} to do the actual work of initializing the
* {@code ServletContext}. The exact process of delegation is described in detail in the
* {@link #onStartup onStartup} documentation below.
*
* <h2>General Notes</h2>
* In general, this class should be viewed as <em>supporting infrastructure</em> for
* the more important and user-facing {@code WebApplicationInitializer} SPI. Taking
* advantage of this container initializer is also completely <em>optional</em>: while
* it is true that this initializer will be loaded and invoked under all Servlet 3.0+
* runtimes, it remains the user's choice whether to make any
* {@code WebApplicationInitializer} implementations available on the classpath. If no
* {@code WebApplicationInitializer} types are detected, this container initializer will
* have no effect.
*
* <p>Note that use of this container initializer and of {@code WebApplicationInitializer}
* is not in any way "tied" to Spring MVC other than the fact that the types are shipped
* in the {@code spring-web} module JAR. Rather, they can be considered general-purpose
* in their ability to facilitate convenient code-based configuration of the
* {@code ServletContext}. In other words, any servlet, listener, or filter may be
* registered within a {@code WebApplicationInitializer}, not just Spring MVC-specific
* components.
*
* <p>This class is neither designed for extension nor intended to be extended.
* It should be considered an internal type, with {@code WebApplicationInitializer}
* being the public-facing SPI.
*
* <h2>See Also</h2>
* See {@link WebApplicationInitializer} Javadoc for examples and detailed usage
* recommendations.<p>
*
* @author Chris Beams
* @author Juergen Hoeller
* @author Rossen Stoyanchev
* @since 3.1
* @see #onStartup(Set, ServletContext)
* @see WebApplicationInitializer
*/
@HandlesTypes(WebApplicationInitializer.class)
public class SpringServletContainerInitializer implements ServletContainerInitializer { /**
* Delegate the {@code ServletContext} to any {@link WebApplicationInitializer}
* implementations present on the application classpath.
* <p>Because this class declares @{@code HandlesTypes(WebApplicationInitializer.class)},
* Servlet 3.0+ containers will automatically scan the classpath for implementations
* of Spring's {@code WebApplicationInitializer} interface and provide the set of all
* such types to the {@code webAppInitializerClasses} parameter of this method.
* <p>If no {@code WebApplicationInitializer} implementations are found on the classpath,
* this method is effectively a no-op. An INFO-level log message will be issued notifying
* the user that the {@code ServletContainerInitializer} has indeed been invoked but that
* no {@code WebApplicationInitializer} implementations were found.
* <p>Assuming that one or more {@code WebApplicationInitializer} types are detected,
* they will be instantiated (and <em>sorted</em> if the @{@link
* org.springframework.core.annotation.Order @Order} annotation is present or
* the {@link org.springframework.core.Ordered Ordered} interface has been
* implemented). Then the {@link WebApplicationInitializer#onStartup(ServletContext)}
* method will be invoked on each instance, delegating the {@code ServletContext} such
* that each instance may register and configure servlets such as Spring's
* {@code DispatcherServlet}, listeners such as Spring's {@code ContextLoaderListener},
* or any other Servlet API componentry such as filters.
* @param webAppInitializerClasses all implementations of
* {@link WebApplicationInitializer} found on the application classpath
* @param servletContext the servlet context to be initialized
* @see WebApplicationInitializer#onStartup(ServletContext)
* @see AnnotationAwareOrderComparator
*/
@Override
public void onStartup(Set<Class<?>> webAppInitializerClasses, ServletContext servletContext)
throws ServletException { List<WebApplicationInitializer> initializers = new LinkedList<WebApplicationInitializer>(); if (webAppInitializerClasses != null) {
for (Class<?> waiClass : webAppInitializerClasses) {
// Be defensive: Some servlet containers provide us with invalid classes,
// no matter what @HandlesTypes says...
if (!waiClass.isInterface() && !Modifier.isAbstract(waiClass.getModifiers()) &&
WebApplicationInitializer.class.isAssignableFrom(waiClass)) {
try {
initializers.add((WebApplicationInitializer) waiClass.newInstance());
}
catch (Throwable ex) {
throw new ServletException("Failed to instantiate WebApplicationInitializer class", ex);
}
}
}
} if (initializers.isEmpty()) {
servletContext.log("No Spring WebApplicationInitializer types detected on classpath");
return;
} servletContext.log(initializers.size() + " Spring WebApplicationInitializers detected on classpath");
AnnotationAwareOrderComparator.sort(initializers);
for (WebApplicationInitializer initializer : initializers) {
initializer.onStartup(servletContext);
}
} }
TODO:
另外, 这个ServletContainerInitializer的执行是在 ServletContextListener之前,可以做个试验看看,这里我写一个简单的TestListener,代码如下
@WebListener
public class TestListener implements ServletContextListener{
@Override
public void contextInitialized(ServletContextEvent sce) {
System.err.println("执行listener ......................");
} @Override
public void contextDestroyed(ServletContextEvent sce) { }
}
同时在上面的ServletApplicationInitializer 的onStartup方法第一行也加一个打印语句:
public class ServletApplicationInitializer implements WebApplicationInitializer {
    @Override
    public void onStartup(ServletContext container) {
        System.err.println("执行3.0 的ServletApplicationInitializer.................");
        //now add the annotations
        AnnotationConfigWebApplicationContext appContext = getContext();
        // Manage the lifecycle of the root application context
        container.addListener(new ContextLoaderListener(appContext));
        container.addListener(new Log4jConfigListener());
        ServletRegistration.Dynamic dispatcher = container.addServlet("DispatcherServlet", new DispatcherServlet(appContext));
        dispatcher.setLoadOnStartup(1);
        dispatcher.addMapping("/");
    }
启动工程,控制台出现:

其实从上面的onStarup代码中就可以看出来:
// Manage the lifecycle of the root application context
container.addListener(new ContextLoaderListener(appContext));
因为ContextLoaderListener是继承ServletContextListener的。
Spring之WebContext不使用web.xml启动 初始化重要的类源码分析(Servlet3.0以上的)的更多相关文章
- ElasticSearch 启动时加载 Analyzer 源码分析
		
ElasticSearch 启动时加载 Analyzer 源码分析 本文介绍 ElasticSearch启动时如何创建.加载Analyzer,主要的参考资料是Lucene中关于Analyzer官方文档 ...
 - 微服务架构 | *2.3 Spring Cloud 启动及加载配置文件源码分析(以 Nacos 为例)
		
目录 前言 1. Spring Cloud 什么时候加载配置文件 2. 准备 Environment 配置环境 2.1 配置 Environment 环境 SpringApplication.prep ...
 - SpringBoot启动代码和自动装配源码分析
		
 随着互联网的快速发展,各种组件层出不穷,需要框架集成的组件越来越多.每一种组件与Spring容器整合需要实现相关代码.SpringMVC框架配置由于太过于繁琐和依赖XML文件:为了方便快速集成第三 ...
 - spring aop 源码分析(三) @Scope注解创建代理对象
		
一.源码环境的搭建: @Component @Scope(scopeName = ConfigurableBeanFactory.SCOPE_SINGLETON,proxyMode = ScopedP ...
 - 【图解源码】Zookeeper3.7源码分析,包含服务启动流程源码、网络通信源码、RequestProcessor处理请求源码
		
Zookeeper3.7源码剖析 能力目标 能基于Maven导入最新版Zookeeper源码 能说出Zookeeper单机启动流程 理解Zookeeper默认通信中4个线程的作用 掌握Zookeepe ...
 - u-boot 源码分析(1) 启动过程分析
		
u-boot 源码分析(1) 启动过程分析 文章目录 u-boot 源码分析(1) 启动过程分析 前言 配置 源码结构 api arch board common cmd drivers fs Kbu ...
 - WebApplicationInitializer究 Spring 3.1之无web.xml式 基于代码配置的servlet3.0应用
		
本文转自http://hitmit1314.iteye.com/blog/1315816 大家应该都已经知道Spring 3.1对无web.xml式基于代码配置的servlet3.0应用.通过spri ...
 - 精尽Spring MVC源码分析 - 寻找遗失的 web.xml
		
该系列文档是本人在学习 Spring MVC 的源码过程中总结下来的,可能对读者不太友好,请结合我的源码注释 Spring MVC 源码分析 GitHub 地址 进行阅读 Spring 版本:5.2. ...
 - 【Spring源码分析系列】启动component-scan类扫描加载过程
		
原文地址:http://blog.csdn.net/xieyuooo/article/details/9089441/ 在spring 3.0以上大家都一般会配置一个Servelet,如下所示: &l ...
 
随机推荐
- 安装python解释器
			
Python目前已支持所有主流操作系统,在Linux,Unix,Mac系统上自带Python环境,在Windows系统上需要安装一下,超简单 打开官网 https://www.python.org/d ...
 - html5--3.16 button元素
			
html5--3.16 button元素 学习要点 掌握button元素的使用 button元素 用来建立一个按钮从功能上来说,与input元素建立的按钮相同 button元素是双标签,其内部可以配置 ...
 - bleve搜索引擎是支持基于field搜索的
			
Query String Query The query language query allows humans to describe complex queries using a simple ...
 - Yii的缓存机制之数据缓存
			
具体说法就是可以缓存变量信息. 设置:Yii::app()->cache->set(名字, 值, 过期时间): 使用:Yii::app()->cache->get(名字); 删 ...
 - 51nod-1119 1119 机器人走方格 V2(组合数学+乘法逆元+快速幂)
			
题目链接: 1119 机器人走方格 V2 基准时间限制:1 秒 空间限制:131072 KB M * N的方格,一个机器人从左上走到右下,只能向右或向下走.有多少种不同的走法?由于方法数量可能很 ...
 - Linux串口通信中一种接收不到数据的问题的解决
			
转载来源:嵌入式系统之初学者点滴 (百度空间) 原文 在这篇文章()中,实现了Linux环境下的串口读写操作,程序也运行成功了.但是再进一步测试时发现,如果开机之后直接如上文中所说,分别运行读程序和写 ...
 - fragment error
			
error: android.view.InflateException: Binary XML file line #6: Error inflating class fragment 解决办法 ...
 - Apple Tree
			
题意: 给一有根树,每个叶子上有一些苹果,现在要求你拿掉一些苹果,使得每一个点的 儿子的子树内的苹果数相同. 解法: 首先可以发现$cnt$个叶子节点之间的关系可以用$cnt-1$个独立方程表示出来. ...
 - 3、webpack打包出的文件解析
			
分析打包后的结果,看看打包后的结果是什么东西 把打包后的结果.注释什么的删删‘’ 当前是一个匿名函数. 默认的时候会执行,执行的时候会传一个对象,对象有几部分,第一部分是我们的key.第二部分是我们的 ...
 - tensorflow weight_variable going
			
# coding: utf-8 import tensorflow as tf from tensorflow.examples.tutorials.mnist import input_data d ...