现在JavaConfig配置方式在逐步取代xml配置方式。而WebApplicationInitializer可以看做是Web.xml的替代,它是一个接口。通过实现WebApplicationInitializer,在其中可以添加servlet,listener等,在加载Web项目的时候会加载这个接口实现类,从而起到web.xml相同的作用。下面就看一下这个接口的详细内容。

首先打开这个接口,如下:


  1. public interface WebApplicationInitializer {
  2. void onStartup(ServletContext var1) throws ServletException;
  3. }

只有一个方法,看不出什么头绪。但是,在这个包下有另外一个类,SpringServletContainerInitializer。它的实现如下:


  1. package org.springframework.web;
  2. import java.lang.reflect.Modifier;
  3. import java.util.Iterator;
  4. import java.util.LinkedList;
  5. import java.util.List;
  6. import java.util.Set;
  7. import javax.servlet.ServletContainerInitializer;
  8. import javax.servlet.ServletContext;
  9. import javax.servlet.ServletException;
  10. import javax.servlet.annotation.HandlesTypes;
  11. import org.springframework.core.annotation.AnnotationAwareOrderComparator;
  12. @HandlesTypes({WebApplicationInitializer.class})
  13. public class SpringServletContainerInitializer implements ServletContainerInitializer {
  14. public SpringServletContainerInitializer() {
  15. }
  16. public void onStartup(Set<Class<?>> webAppInitializerClasses, ServletContext servletContext) throws ServletException {
  17. List<WebApplicationInitializer> initializers = new LinkedList();
  18. Iterator var4;
  19. if(webAppInitializerClasses != null) {
  20. var4 = webAppInitializerClasses.iterator();
  21. while(var4.hasNext()) {
  22. Class<?> waiClass = (Class)var4.next();
  23. if(!waiClass.isInterface() && !Modifier.isAbstract(waiClass.getModifiers()) && WebApplicationInitializer.class.isAssignableFrom(waiClass)) {
  24. try {
  25. initializers.add((WebApplicationInitializer)waiClass.newInstance());
  26. } catch (Throwable var7) {
  27. throw new ServletException("Failed to instantiate WebApplicationInitializer class", var7);
  28. }
  29. }
  30. }
  31. }
  32. if(initializers.isEmpty()) {
  33. servletContext.log("No Spring WebApplicationInitializer types detected on classpath");
  34. } else {
  35. servletContext.log(initializers.size() + " Spring WebApplicationInitializers detected on classpath");
  36. AnnotationAwareOrderComparator.sort(initializers);
  37. var4 = initializers.iterator();
  38. while(var4.hasNext()) {
  39. WebApplicationInitializer initializer = (WebApplicationInitializer)var4.next();
  40. initializer.onStartup(servletContext);
  41. }
  42. }
  43. }
  44. }

这个类就比较有意思了,先不管其他的,读一下这段代码,可以得到这样的意思。

先判断webAppInitializerClasses这个Set是否为空。如果不为空的话,找到这个set中不是接口,不是抽象类,并且是

WebApplicationInitializer接口实现类的类,将它们保存到list中。当这个list为空的时候,抛出异常。不为空的话就按照一定的顺序排序,并将它们按照一定的顺序实例化。调用其onStartup方法执行。到这里,就可以解释WebApplicationInitializer实现类的工作过程了。但是,在web项目运行的时候,SpringServletContainerInitializer这个类又是怎样被调用的呢。

它只有一个接口,ServletContainerInitializer,通过它就可以解释SpringServletContainerInitializer是如何被调用的。它的内容如下,


  1. package javax.servlet;
  2. import java.util.Set;
  3. public interface ServletContainerInitializer {
  4. void onStartup(Set<Class<?>> var1, ServletContext var2) throws ServletException;
  5. }

首先,这个接口是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。内容如下:


  1. public interface WebParameter {
  2. void loadOnstarp(ServletContext servletContext);
  3. }

可以在这里面添加servlet,listener等。

2、定义Servlet。


  1. public class MyServlet extends HttpServlet {
  2. @Override
  3. protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
  4. resp.getWriter().write("TestSetvlet");
  5. }
  6. }

3、定义MyWebParameter作为WebParameter的实现类,将Servlet添加到上下文,并设置好映射。


  1. public class MyWebParameter implements WebParameter {
  2. public void loadOnstarp(ServletContext servletContext) {
  3. ServletRegistration.Dynamic testSetvelt=servletContext.addServlet("test","com.test.servlet.MyServlet");
  4. testSetvelt.setLoadOnStartup(1);
  5. testSetvelt.addMapping("/test");
  6. }
  7. }

4、定义好WebConfig作为ServletContainerInitializer的实现类,它的作用是扫描找到WebParameter的实现类,并调用其方法。


  1. @HandlesTypes({WebParameter.class})
  2. public class WebConfig implements ServletContainerInitializer {
  3. public void onStartup(Set<Class<?>> set, ServletContext servletContext) throws ServletException {
  4. Iterator var4;
  5. if (set!=null){
  6. var4=set.iterator();
  7. while(var4.hasNext()){
  8. Class<?> clazz= (Class<?>) var4.next();
  9. if (!clazz.isInterface()&& !Modifier.isAbstract(clazz.getModifiers())&&WebParameter.class.isAssignableFrom(clazz)){
  10. try {
  11. ((WebParameter) clazz.newInstance()).loadOnstarp(servletContext);
  12. }catch (Exception e){
  13. e.printStackTrace();
  14. }
  15. }
  16. }
  17. }
  18. }
  19. }

5、根据SPI机制,定义一个META-INF/services文件夹,并在其下定义相关文件名称,并将WebConfig的类全名称填入其中。

至此,相关内容就完成了,因为我用的maven,通过install将其作为jar包上传到本地仓库。从另外一个web项目调用这个包进行访问。

6、最终结果:

    

相关代码请转至我的github点击打开链接

ps:其中涉及到了SPI相关的内容,如果不懂请自行百度。如果认识有误,请大佬指出,谢谢。

Spring中WebApplicationInitializer的理解的更多相关文章

  1. Spring中IOC的理解

    Spring中IOC的理解 1.什么是IOC? (1)控制反转.把对象创建和对象间的调用过程交给Spring进行管理. (2)使用IOC的目的:为了耦合度降低. 2.IOC底层原理? (1)xml解析 ...

  2. 关于Spring中AOP的理解

    AOP简介[理解][重点] 1.AOP(Aspect Oriented Programing)面向切面/方面编程 2.AOP隶属软件工程的范畴,指导开发人员如何制作开发软件,进行结构设计 3.AOP联 ...

  3. 浅析对spring中IOC的理解

    学习过Spring框架的人一定都会听过Spring的IoC(控制反转) .DI(依赖注入)这两个概念,对于初学Spring的人来说,总觉得IoC .DI这两个概念是模糊不清的,是很难理解的,今天和大家 ...

  4. Spring中AOP的理解

    1.AOP的概念 AOP(AspectOriented Programming,面向切面编程)指的是可以通过预编译方式和运行期动态代理实现在不修改源代码的情况下个程序动态统一添加功能的一种技术.AOP ...

  5. Spring中Configuration的理解

    基本用途从Spring3.0,@Configuration用于定义配置类,可替换xml配置文件,被注解的类内部包含有一个或多个被@Bean注解的方法,这些方法将会被AnnotationConfigAp ...

  6. spring中的ResponseEntity理解

    参考: https://blog.csdn.net/weixin_37869477/article/details/82762976 https://blog.csdn.net/sswqzx/arti ...

  7. 深入理解spring中的各种注解

    Spring中的注解大概可以分为两大类: 1)spring的bean容器相关的注解,或者说bean工厂相关的注解: 2)springmvc相关的注解. spring的bean容器相关的注解,先后有:@ ...

  8. Spring学习(二)——Spring中的AOP的初步理解[转]

      [前面的话] Spring对我太重要了,做个关于web相关的项目都要使用Spring,每次去看Spring相关的知识,总是感觉一知半解,没有很好的系统去学习一下,现在抽点时间学习一下Spring. ...

  9. 深入理解spring中的各种注解(转)

    Spring中的注解大概可以分为两大类: 1)spring的bean容器相关的注解,或者说bean工厂相关的注解: 2)springmvc相关的注解. spring的bean容器相关的注解,先后有:@ ...

随机推荐

  1. programming+windows+MFC

    1)CMyApp declares no data members 2)CWinApp::InitInstance run after application build but before the ...

  2. NAACL 2013 Paper Mining User Relations from Online Discussions using Sentiment Analysis and PMF

    中文简单介绍:本文对怎样基于情感分析和概率矩阵分解从网络论坛讨论中挖掘用户关系进行了深入研究. 论文出处:NAACL'13. 英文摘要: Advances in sentiment analysis ...

  3. Android多线程研究(6)——多线程之间数据隔离

    在上一篇<Android多线程研究(5)--线程之间共享数据>中对线程之间的数据共享进行了学习和研究,这一篇我们来看看怎样解决多个线程之间的数据隔离问题,什么是数据隔离呢?比方说我们如今开 ...

  4. 接口如何使用(以笑话大全api为例)

    接口如何使用(以笑话大全api为例) 一.总结 一句话总结:直接用ajax,或者post,get方式向接口网址请求数据,然后接收网站传过来的数据就好,和我们写网站的时候前台向后台请求数据的方式一样. ...

  5. JQ实现选项卡(jQuery原型插件扩展)

    下边分为两个版本,一种是点击切换选项(index.js),一种是滑过切换选项(index1.js) HTML文件: jq使用jquery-1.11.3.js版本 <!DOCTYPE html&g ...

  6. Javascript和jquery事件--阻止事件冒泡和阻止默认事件

    阻止冒泡和阻止默认事件—js和jq相同,jq的event是一个全局的变量 我们写代码的时候常用的都是事件冒泡,但是有的时候我们并不需要触发父元素的事件,而浏览器也有自己的默认行为(表单提交.超链接跳转 ...

  7. Spring Boot集成EHCache实现缓存机制

    SpringBoot 缓存(EhCache 2.x 篇) SpringBoot 缓存 在 Spring Boot中,通过@EnableCaching注解自动化配置合适的缓存管理器(CacheManag ...

  8. (7)Launcher3客制化之,改动单屏幕后,Fix在Hotseat拖动应用删除报错

    改动单屏幕后,在workspace里面拖动图标.到删除button上松开的时候,报错问题. 而且无法再次显示拖动的图标. 拖动松开手时候触发 public void onDropCompleted(f ...

  9. 内存、时间复杂度、CPU/GPU以及运行时间

    衡量 CPU 的计算能力: 比如一个 Intel 的 i5-2520M @2.5 Ghz 的处理器, 则其计算能力 2.5 * 4(4核) = 10 GFLOPS FLOP/s,Floating-po ...

  10. ARCGIS动态画点

    小马哥淡定 原文 ARCGIS动态画点 private void DrawPointOnMap(double x, double y,bool clear) { IMapControl2 pMapCt ...