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 ...
随机推荐
- JDBCTool
新建 *.properties属性文件,内容如下: driver=com.mysql.jdbc.Driver url=jdbc:mysql://localhost:3306/dbName userna ...
- FFmpeg在Linux下搭建 ***
今天介绍下FFmpeg在Linux下安装编译过程,总体过程比较顺利,就是在ffmpeg等的时间稍长点,仅当记录. 关于FFmpeg FFmpeg是一个开源免费跨平台的视频和音频流方案,属于自由软件,采 ...
- SKINTOOL 系统不能正常运行
1..net安装 2.Microsoft Visual C++ Redistributable Package 运行库
- JQ实现图片上传预览功能
<input type="file" name="img" id="test1"> <img src="&quo ...
- Git(二)--常用命令
$ git init 从当前目录初始化 $ git clone git://xxxx 从远程仓库克隆 $ git status 确定哪些文件当前处于什么状态 $ git add 开始跟踪一个新文件 ...
- hue集成各种组件
一.Hue安装 可以编译安装,我这里有已经编译好的,直接解压使用: hue默认端口:8888 http://gethue.com/ https://github.com/cloudera/hue ht ...
- 1-1 课程简介 & 2-1 IDEA与Eclipse的不同 & 2-3 Intellij IDEA安装
---恢复内容开始--- F:\教程\java-慕课\从网页搭建入门Java Web\Java web\步骤四:常用功能\1.IntelliJ IDEA开发工具入门 1-1 课程简介 2-1 IDEA ...
- Jmeter + Junit
在使用jmeter中Junit的功能之前,最好将接口以手动的方式调通,可以参考 Jmeter之HTTP Request 下面开始讲一下如何使用Junit功能 1. 编写测试类 JmeterJunit ...
- Linux文件IO操作函数概述
文件概述 Linux中,一切皆文件.文件为操作系统服务和设备提供了一个简单而一致的接口.这意味着程序完全可以像使用文件那样使用磁盘文件.串行口.打印机和其他设备. 也就是说,大多数情况下,你只需要使用 ...
- (2)ASP.NET Core 依赖关系注入(服务)
1.前言 面向对象设计(OOD)里有一个重要的思想就是依赖倒置原则(DIP),并由该原则牵引出依赖注入(DI).控制反转(IOC)及其容器等老生常谈的概念,初学者很容易被这些概念搞晕(包括我在内),在 ...