实现WebApplicationinitializer接口的类都可以在web应用程序启动时被加载。

那么来想一个问题:为什么实现了WebApplicationInitializer这个接口后,onStartup方法就会自动执行?

我们来简单分析一下它的实现原理,下面先贴上WebApplicationInitializer接口相关代码:

servlet的ServletContainerInitializer接口:

package javax.servlet;

import java.util.Set;

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 类(从本类开始以下代码都是spring的代码):
package org.springframework.web;

import java.lang.reflect.Modifier;
import java.util.LinkedList;
import java.util.List;
import java.util.ServiceLoader;
import java.util.Set;
import javax.servlet.ServletContainerInitializer;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.annotation.HandlesTypes; import org.springframework.core.annotation.AnnotationAwareOrderComparator;
@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;
} AnnotationAwareOrderComparator.sort(initializers);
servletContext.log("Spring WebApplicationInitializers detected on classpath: " + initializers); for (WebApplicationInitializer initializer : initializers) {
initializer.onStartup(servletContext);
}
} }

WebApplicationInitializer接口(本文讨论的接口):

package org.springframework.web;

import javax.servlet.ServletContext;
import javax.servlet.ServletException
public interface WebApplicationInitializer { /**
* Configure the given {@link ServletContext} with any servlets, filters, listeners
* context-params and attributes necessary for initializing this web application. See
* examples {@linkplain WebApplicationInitializer above}.
* @param servletContext the {@code ServletContext} to initialize
* @throws ServletException if any call against the given {@code ServletContext}
* throws a {@code ServletException}
*/
void onStartup(ServletContext servletContext) throws ServletException; }

javax.servlet.ServletContainerInitializer文件(在路径:spring-framework/spring-web/src/main/resources/META-INF/services/下)

该文件文件名就是“javax.servlet.ServletContainerInitializer”,其内容只有下面这行

org.springframework.web.SpringServletContainerInitializer

至此,相关代码/文件,都在上面给出了。

那么请看SpringServletContainerInitializer类,它实现了 Servlet 的ServletContainerInitializer接口,并且有"@HandlesTypes(WebApplicationInitializer.class) "注解,这个注解指明了ServletContainerInitializer接口可以使用的类。

并且必须在 spring-web-X.X.X.RELEASE-sources.jar 文件下,的META_INF/services路径下有个名为“
javax.servlet.ServletContainerInitializer”的文件,文件中的内容与
ServletContainerIntializer的实现类全限定名相同(请参考上面贴出的代码)。这样,web应用启动时,程序就会找到WebApplicationInitializer这个接口的实现类,并调用onStartup方法。

如果说得不对的地方,请指正,谢谢

参考:

http://blog.csdn.net/sunhuwh/article/details/25441217

http://blog.csdn.net/sunhuwh/article/details/25504061

spring源码:https://github.com/spring-projects/spring-framework

原创文章,转载请注明:http://www.cnblogs.com/langtianya/p/5393633.html

WebApplicationInitializer (spring 3.x.x以上版本)的更多相关文章

  1. Spring官网下载各版本jar包

    1:浏览器输入官网地址:http://spring.io/projects 2:点击如图树叶页面按钮.  3:点击如图小猫图片按钮.  4:查找downloading spring artifacts ...

  2. Spring Cloud 升级最新 Finchley 版本,踩坑指南!

    https://blog.csdn.net/youanyyou/article/details/81530240 Spring Cloud 升级最新 Finchley 版本,踩了所有的坑! 2018年 ...

  3. Spring Cloud 升级最新 Greenwich 版本,舒服了~

    去年将 Spring Cloud 升级到了 Finchley 版本: Spring Cloud 升级最新 Finchley 版本,踩了所有的坑! 这个大版本栈长是踩了非常多的坑啊,帮助了不少小伙伴. ...

  4. 厉害了,Spring Cloud Alibaba 发布 GA 版本!

    ? 小马哥 & Josh Long ? 喜欢写一首诗一般的代码,更喜欢和你共同 code review,英雄的相惜,犹如时间沉淀下来的对话,历久方弥新. 相见如故,@杭州. 4 月 18 日, ...

  5. Spring Cloud 2021.0.0 正式发布,第一个支持Spring Boot 2.6的版本!

    美国时间12月2日,Spring Cloud 正式发布了第一个支持 Spring Boot 2.6 的版本,版本号为:2021.0.0,codename 为 Jubilee. 在了解具体更新内容之前, ...

  6. InstallShield 2012 Spring优惠升级到最新版本(2015.4.30之前)

    InstallShield 2012 Spring即将EOF,所以仍在使用InstallShield 2012 Spring的用户请注意下面内容: InstallShield 2012 Spring升 ...

  7. spring集成mongodb jar包版本问题

    在开发过程中,spring集成mongodb的jar包. 如果需要使用排序功能. spring-data-mongodb-1.4.1.RELEASE.jar 的版本为1.4.1,如果使用如下代码: Q ...

  8. spring官网上下载历史版本的spring插件,springsource-tool-suite

    spring官网下载地址(https://spring.io/tools/sts/all),历史版本地址(https://spring.io/tools/sts/legacy). 注:历史版本下载的都 ...

  9. Spring Cloud 升级最新 Finchley 版本,踩了所有的坑!

    Spring Boot 2.x 已经发布了很久,现在 Spring Cloud 也发布了 基于 Spring Boot 2.x 的 Finchley 版本,现在一起为项目做一次整体框架升级. 升级前 ...

随机推荐

  1. (转)String、StringBuffer与StringBuilder之间区别

    原文地址: http://www.cnblogs.com/A_ming/archive/2010/04/13/1711395.html 关于这三个类在字符串处理中的位置不言而喻,那么他们到底有什么优缺 ...

  2. jquery常用函数与方法

    1.delay(duration,[queueName]) 设置一个延时来推迟执行队列中之后的项目.jQuery 1.4新增.用于将队列中的函数延时执行.他既可以推迟动画队列的执行,也可以用于自定义队 ...

  3. BZOJ1878: [SDOI2009]HH的项链[树状数组 离线]

    1878: [SDOI2009]HH的项链 Time Limit: 4 Sec  Memory Limit: 64 MBSubmit: 3486  Solved: 1738[Submit][Statu ...

  4. POJ1962Corporative Network[带权并查集]

    Corporative Network Time Limit: 3000MS   Memory Limit: 30000K Total Submissions: 3945   Accepted: 14 ...

  5. 用MATLAB对信号做频谱分析

    1.首先学习下傅里叶变换的东西.学高数的时候老师只是将傅里叶变换简单的说了下,并没有深入的讲解.而现在看来,傅里叶变换似乎是信号处理的方面的重点只是呢,现在就先学习学习傅里叶变换吧. 上面这幅图在知乎 ...

  6. SQL编程

    变量: 变量是一块内存空间的表示, 数组是一连串空间 如何定义一个变量 第一套变量定义  整型 Declare @num int Set @num=10 Print @num 第二套变量定义   字符 ...

  7. 第22章 java线程(2)-线程同步

    java线程(2)-线程同步 本节主要是在前面吃苹果的基础上发现问题,然后提出三种解决方式 1.线程不安全问题 什么叫线程不安全呢 即当多线程并发访问同一个资源对象的时候,可能出现不安全的问题 对于前 ...

  8. jmeter(五)Sample之JDBC Request

    jmeter中取样器(Sampler)是与服务器进行交互的单元.一个取样器通常进行三部分的工作:向服务器发送请求,记录服务器的响应数据和记录相应时间信息 有时候工作中我们需要对数据库发起请求或者对数据 ...

  9. Spring知识点提炼

    原文出处: 朱小厮 1. Spring框架的作用 轻量:Spring是轻量级的,基本的版本大小为2MB 控制反转:Spring通过控制反转实现了松散耦合,对象们给出它们的依赖,而不是创建或查找依赖的对 ...

  10. Apache 配置虚拟主机三种方式

    一.基于IP 1. 假设服务器有个IP地址为192.168.1.10,使用ifconfig在同一个网络接口eth0上绑定3个IP: [root@localhost root]# ifconfig et ...