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容器相关的注解,先后有:@ ...
随机推荐
- Java Web学习总结(17)——JSP属性范围
所谓的属性范围就是一个属性设置之后,可以经过多少个其他页面后仍然可以访问的保存范围. 一.JSP属性范围 JSP中提供了四种属性范围,四种属性范围分别指以下四种: 当前页:一个属性只能在一个页面中取得 ...
- 黑马day01 xml 的解析方式
XML编程:利用java程序去增删改查(CRUD)xml中的数据 解析思想: dom解析 sax解析 基于这两种解析思想市面上就有了非常多的解析api sun jaxp既有dom方式也有sax方式,而 ...
- 【MemSQL Start[c]UP 3.0 - Round 1 B】 Lazy Security Guard
[链接]h在这里写链接 [题意] 围成对应面积的方块最少需要多少条边. [题解] 有特定的公式的. 2*ceil(2*根号下(n)); -> 自己找下规律也很简单的. [错的次数] 0 [反思] ...
- 洛谷——P1011 车站
https://www.luogu.org/problem/show?pid=1011#sub 题目描述 火车从始发站(称为第1站)开出,在始发站上车的人数为a,然后到达第2站,在第2站有人上.下车, ...
- PHP回调函数--call_user_func_array
我这是抄的 感谢 https://www.cnblogs.com/zzl-21086595/p/4547519.html 全局函数的回调 这里的全局函数的意思,是直接使用function定义的函数,它 ...
- 使用u盘量产工具修复写保护的u盘
自己的u盘突然提示写保护,而且也没有写保护开关,怎么都写不进文件,试了很多办法都无法去除写保护,最后找了一个u盘量产工具,搞定: 插上u盘后,会检测到u盘,点“开始"后静静等待它完成,u盘又 ...
- iOS数据存储简要笔记
1. 数据存储常用的方式 (1)XML 属性列表(plist)归档 (2)preference(偏好设置) (3)NSKeyedArchiver归档(NSCoding) (4) SQLite3 ...
- 洛谷 偷天换日&&“访问”美术馆
典型的树形DP 按理说是先做“访问美术馆”再做偷天换日. 但是我先做了偷天换日然后再做的“访问”美术馆 DP方程好推,偷天换日在遇到有展品的时候做背包,因为是先做的偷天换日,所以把偷天换日的输入w,c ...
- Delphi的指针(有图,很清楚)
Pointers are like jumps, leading wildly from one part of the data structure to another. Their introd ...
- 12行Python暴力爬《黑豹》豆瓣短评
作者:黄嘉锋 来源:https://www.jianshu.com/p/ea0b56e3bd86 草长莺飞,转眼间又到了三月"爬虫月".这时往往不少童鞋写论文苦于数据获取艰难,辗转 ...