Spring中WebApplicationInitializer的理解
现在JavaConfig配置方式在逐步取代xml配置方式。而WebApplicationInitializer可以看做是Web.xml的替代,它是一个接口。通过实现WebApplicationInitializer,在其中可以添加servlet,listener等,在加载Web项目的时候会加载这个接口实现类,从而起到web.xml相同的作用。下面就看一下这个接口的详细内容。
首先打开这个接口,如下:
-
public interface WebApplicationInitializer {
-
void onStartup(ServletContext var1) throws ServletException;
-
}
只有一个方法,看不出什么头绪。但是,在这个包下有另外一个类,SpringServletContainerInitializer。它的实现如下:
-
package org.springframework.web;
-
-
import java.lang.reflect.Modifier;
-
import java.util.Iterator;
-
import java.util.LinkedList;
-
import java.util.List;
-
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 {
-
public SpringServletContainerInitializer() {
-
}
-
-
public void onStartup(Set<Class<?>> webAppInitializerClasses, ServletContext servletContext) throws ServletException {
-
List<WebApplicationInitializer> initializers = new LinkedList();
-
Iterator var4;
-
if(webAppInitializerClasses != null) {
-
var4 = webAppInitializerClasses.iterator();
-
-
while(var4.hasNext()) {
-
Class<?> waiClass = (Class)var4.next();
-
if(!waiClass.isInterface() && !Modifier.isAbstract(waiClass.getModifiers()) && WebApplicationInitializer.class.isAssignableFrom(waiClass)) {
-
try {
-
initializers.add((WebApplicationInitializer)waiClass.newInstance());
-
} catch (Throwable var7) {
-
throw new ServletException("Failed to instantiate WebApplicationInitializer class", var7);
-
}
-
}
-
}
-
}
-
-
if(initializers.isEmpty()) {
-
servletContext.log("No Spring WebApplicationInitializer types detected on classpath");
-
} else {
-
servletContext.log(initializers.size() + " Spring WebApplicationInitializers detected on classpath");
-
AnnotationAwareOrderComparator.sort(initializers);
-
var4 = initializers.iterator();
-
-
while(var4.hasNext()) {
-
WebApplicationInitializer initializer = (WebApplicationInitializer)var4.next();
-
initializer.onStartup(servletContext);
-
}
-
-
}
-
}
-
}
这个类就比较有意思了,先不管其他的,读一下这段代码,可以得到这样的意思。
先判断webAppInitializerClasses这个Set是否为空。如果不为空的话,找到这个set中不是接口,不是抽象类,并且是
WebApplicationInitializer接口实现类的类,将它们保存到list中。当这个list为空的时候,抛出异常。不为空的话就按照一定的顺序排序,并将它们按照一定的顺序实例化。调用其onStartup方法执行。到这里,就可以解释WebApplicationInitializer实现类的工作过程了。但是,在web项目运行的时候,SpringServletContainerInitializer这个类又是怎样被调用的呢。
它只有一个接口,ServletContainerInitializer,通过它就可以解释SpringServletContainerInitializer是如何被调用的。它的内容如下,
-
package javax.servlet;
-
-
import java.util.Set;
-
-
public interface ServletContainerInitializer {
-
void onStartup(Set<Class<?>> var1, ServletContext var2) throws ServletException;
-
}
首先,这个接口是javax.servlet下的。官方的解释是这样的:为了支持可以不使用web.xml。提供了ServletContainerInitializer,它可以通过SPI机制,当启动web容器的时候,会自动到添加的相应jar包下找到META-INF/services下以ServletContainerInitializer的全路径名称命名的文件,它的内容为ServletContainerInitializer实现类的全路径,将它们实例化。既然这样的话,那么SpringServletContainerInitializer作为ServletContainerInitializer的实现类,它的jar包下也应该有相应的文件。打开查看如下:
哈,现在就可以解释清楚了。首先,SpringServletContainerInitializer作为ServletContainerInitializer的实现类,通过SPI机制,在web容器加载的时候会自动的被调用。(这个类上还有一个注解@HandlesTypes,它的作用是将感兴趣的一些类注入到ServletContainerInitializerde), 而这个类的方法又会扫描找到WebApplicationInitializer的实现类,调用它的onStartup方法,从而起到启动web.xml相同的作用。
然后,我们自己通过一个实例来实现相同的功能,通过一样的方式来访问一个servlet。
1、定义接口WebParameter,它就相当于WebApplicationInitializer。内容如下:
-
public interface WebParameter {
-
-
void loadOnstarp(ServletContext servletContext);
-
}
可以在这里面添加servlet,listener等。
2、定义Servlet。
-
public class MyServlet extends HttpServlet {
-
@Override
-
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
-
resp.getWriter().write("TestSetvlet");
-
}
-
}
3、定义MyWebParameter作为WebParameter的实现类,将Servlet添加到上下文,并设置好映射。
-
public class MyWebParameter implements WebParameter {
-
public void loadOnstarp(ServletContext servletContext) {
-
ServletRegistration.Dynamic testSetvelt=servletContext.addServlet("test","com.test.servlet.MyServlet");
-
testSetvelt.setLoadOnStartup(1);
-
testSetvelt.addMapping("/test");
-
}
-
}
4、定义好WebConfig作为ServletContainerInitializer的实现类,它的作用是扫描找到WebParameter的实现类,并调用其方法。
-
@HandlesTypes({WebParameter.class})
-
public class WebConfig implements ServletContainerInitializer {
-
public void onStartup(Set<Class<?>> set, ServletContext servletContext) throws ServletException {
-
Iterator var4;
-
if (set!=null){
-
var4=set.iterator();
-
while(var4.hasNext()){
-
Class<?> clazz= (Class<?>) var4.next();
-
if (!clazz.isInterface()&& !Modifier.isAbstract(clazz.getModifiers())&&WebParameter.class.isAssignableFrom(clazz)){
-
try {
-
((WebParameter) clazz.newInstance()).loadOnstarp(servletContext);
-
}catch (Exception e){
-
e.printStackTrace();
-
}
-
}
-
}
-
}
-
}
-
}
5、根据SPI机制,定义一个META-INF/services文件夹,并在其下定义相关文件名称,并将WebConfig的类全名称填入其中。
至此,相关内容就完成了,因为我用的maven,通过install将其作为jar包上传到本地仓库。从另外一个web项目调用这个包进行访问。
6、最终结果:
相关代码请转至我的github点击打开链接
ps:其中涉及到了SPI相关的内容,如果不懂请自行百度。如果认识有误,请大佬指出,谢谢。
Spring中WebApplicationInitializer的理解的更多相关文章
- Spring中IOC的理解
Spring中IOC的理解 1.什么是IOC? (1)控制反转.把对象创建和对象间的调用过程交给Spring进行管理. (2)使用IOC的目的:为了耦合度降低. 2.IOC底层原理? (1)xml解析 ...
- 关于Spring中AOP的理解
AOP简介[理解][重点] 1.AOP(Aspect Oriented Programing)面向切面/方面编程 2.AOP隶属软件工程的范畴,指导开发人员如何制作开发软件,进行结构设计 3.AOP联 ...
- 浅析对spring中IOC的理解
学习过Spring框架的人一定都会听过Spring的IoC(控制反转) .DI(依赖注入)这两个概念,对于初学Spring的人来说,总觉得IoC .DI这两个概念是模糊不清的,是很难理解的,今天和大家 ...
- Spring中AOP的理解
1.AOP的概念 AOP(AspectOriented Programming,面向切面编程)指的是可以通过预编译方式和运行期动态代理实现在不修改源代码的情况下个程序动态统一添加功能的一种技术.AOP ...
- Spring中Configuration的理解
基本用途从Spring3.0,@Configuration用于定义配置类,可替换xml配置文件,被注解的类内部包含有一个或多个被@Bean注解的方法,这些方法将会被AnnotationConfigAp ...
- spring中的ResponseEntity理解
参考: https://blog.csdn.net/weixin_37869477/article/details/82762976 https://blog.csdn.net/sswqzx/arti ...
- 深入理解spring中的各种注解
Spring中的注解大概可以分为两大类: 1)spring的bean容器相关的注解,或者说bean工厂相关的注解: 2)springmvc相关的注解. spring的bean容器相关的注解,先后有:@ ...
- Spring学习(二)——Spring中的AOP的初步理解[转]
[前面的话] Spring对我太重要了,做个关于web相关的项目都要使用Spring,每次去看Spring相关的知识,总是感觉一知半解,没有很好的系统去学习一下,现在抽点时间学习一下Spring. ...
- 深入理解spring中的各种注解(转)
Spring中的注解大概可以分为两大类: 1)spring的bean容器相关的注解,或者说bean工厂相关的注解: 2)springmvc相关的注解. spring的bean容器相关的注解,先后有:@ ...
随机推荐
- MES制造系统
给大家介绍一个非常不错的MES专业产品网站,http://www.OrBitMES.com 上面分为初.中.高各级的难得的MES产品学习资料下载, http://www.orbitmes.com/Pr ...
- c++ 常识
1) 功能:格式化字符串输出 说明:format指定输出格式,后面跟要输出的变量 目前printf支持以下格式: %c 单个字符 ...
- 洛古——P1433 吃奶酪
https://www.luogu.org/problem/show?pid=1433 题目描述 房间里放着n块奶酪.一只小老鼠要把它们都吃掉,问至少要跑多少距离?老鼠一开始在(0,0)点处. 输入输 ...
- ajax对服务端发送请求
//兼容处理获取ajax对象 var req = ''; if (window.XMLHttpRequest) req = new XMLHttpRequest(); else req = ...
- GO语言学习(四)GO语言语言结构
Go Hello World 实例 Go 语言的基础组成有以下几个部分: 包声明 引入包 函数 变量 语句 & 表达式 注释 接下来让我们来看下简单的代码,该代码输出了"Hello ...
- 扩展的方法:es6 安装模块builder
https://github.com/es-shims/es5-shim/ Image.png 检测浏览器可支持es5,不支持就扩展,做兼容: 扩展的方法: Image.png 取所有对象的键值: o ...
- vim编辑器经常使用命令
高级一些的编辑器,都会包括宏功能,vim当然不能缺少了.在vim中使用宏是很方便的: :qx 開始记录宏,并将结果存入寄存器xq 退出记录模式@x 播放记录在x寄存器中的宏命令 ...
- [Nuxt] Display Vuex Data Differently in Each Page of Nuxt and Vue.js
You often use the same data in different ways across pages. This lesson walks you through setting up ...
- [Err] 1136 - Column count doesn't match value count at row 1
1 错误描写叙述 [Err] 1136 - Column count doesn't match value count at row 1 Procedure execution failed 113 ...
- Genymotion加入模拟器时报“Unable to create virtual device,Server returned HTTP status code 0”
今天也遇到这个问题,算是对这个文章的一点补充 打开图中这个文件 C:\Users\xxx\AppData\Local\Genymobile 搜索 [downloadFile] 找到这个一串URL ht ...