实现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. linux特殊权限SUID、SGID、SBIT

    对于linux中文件或目录的权限,应该都知道普通的rwx权限(关于linux中rwx权限的看我的这篇博文http://www.cnblogs.com/javaee6/p/3994750.html).我 ...

  2. Linux 下.desktop 桌面程序图标文件编写方式

    [Desktop Entry] //每个desktop文件都以这个标签开始,说明这是一个Desktop Entry文件 Version = 1.0 //标明Desktop Entry的版本(可选) N ...

  3. Shell编程和Vim操作

    其实一直不懂什么是shell,安卓adb调试时会使用一些简单的shell命令,总结一下 1.adb调试命令 全称:Android Debug Bridge 设置: export PATH=${PATH ...

  4. [HTML表格]在databases显示行的附加信息

    模板代码: <!-- DataTables CSS --> <link rel="stylesheet" href="{% static 'DataTa ...

  5. 洛谷P1262 间谍网络[强连通分量 BFS]

    题目描述 由于外国间谍的大量渗入,国家安全正处于高度的危机之中.如果A间谍手中掌握着关于B间谍的犯罪证据,则称A可以揭发B.有些间谍收受贿赂,只要给他们一定数量的美元,他们就愿意交出手中掌握的全部情报 ...

  6. Java设计模式之单例

    一.Java中的单例: 特点: ① 单例类只有一个实例 ② 单例类必须自己创建自己唯一实例 ③ 单例类必须给所有其他对象提供这一实例 二.两种模式: ①懒汉式单例<线程不安全> 在类加载时 ...

  7. BroadcastReceiver详解

    详解 2014-08-20 19:42 13492人阅读 评论(8) 收藏 举报 分类: 5.andriod开发(148) 版权声明:本文为博主原创文章,未经博主允许不得转载.   目录(?)[+] ...

  8. C#.NET 大型企业信息化系统集成快速开发平台 4.2 版本 - 几十套业务系统集中统一授权管理实现经验分享

    由于这几年互联网电商的快速发展,快递公司也进入了快速发展的绝好快速成长期.随着社会的强劲需求公司的业绩年年攀新高.快速发展的公司都需要有强大的IT信息系统,硬件设备基本上款到了货也可以到了,但是软件系 ...

  9. sql server 排名函数:DENSE_RANK

    一.需求 之前sql server 的排名函数用得最多的应该是RoW_NUMBER()了,我通常用ROW_NUMBER() + CTE 来实现分页:今天逛园,看到另一个内置排名函数还不错,自己顺便想了 ...

  10. 【swift学习笔记】二.页面转跳数据回传

    上一篇我们介绍了页面转跳:[swift学习笔记]一.页面转跳的条件判断和传值 这一篇说一下如何把数据回传回父页面,如下图所示,这个例子很简单,只是把传过去的数据加上了"回传"两个字 ...