1. 总结1:
    1. SCI:Servlet容器(Tomcat)提供的初始化Servlet容器本身的接口,可替换web.xml
    2. SpringSCI:SpringServletContainerInitializer,Srping提供的SCI的一个实现,起到中转桥接作用,桥接到 WebApplicationInitializer 接口上
    3. WebApplicationInitializer :可以自定义配置servlet、listener,进而可以通过代码手动控制两个上下文的创建过程(参考:基于xml     参考:支持注解);只能创建上线文但不能配置上下文详细内容,但可以指定上下文配置文件的路径或配置类的类路径
    4. AbstractAnnotationConfigDispatcherServletInitializer:将两个上下文自动已创建好,已创建好的上下文的类型都是支持注解的;手动继承后只需要指定两个上下文配置类路径即可。
    5. WebMvcConfigurer:

      WebMvcConfigurationAdapter已经废弃,最好用implements WebMvcConfigurer代替

      @Configuration
      public class MyConfig implements WebMvcConfigurer { }

      如果使用继承,WebMvcConfigurationSupport,DelegatingWebMvcConfiguration,或者使用@EnableWebMvc

    6. If you want to keep Spring Boot MVC features and you want to add additional MVC configuration (interceptors, formatters, view controllers, and other features), you can add your own @Configuration class of type WebMvcConfigurer but without @EnableWebMvc. If you wish to provide custom instances of RequestMappingHandlerMapping, RequestMappingHandlerAdapter, or ExceptionHandlerExceptionResolver, you can declare a WebMvcRegistrationsAdapter instance to provide such components.

      If you want to take complete control of Spring MVC, you can add your own @Configuration annotated with @EnableWebMvc.

  2. 总结2:
    1. java提供SPI,用于加载指定接口的 特定实现类
    2. servlet容器提供SCI接口,用于配置servlet容器初始化;这个过程使用了java的SPI机制;类似Logfactory的工作原理
    3. Spring提供SpringServletContainerInitializer类(该类实现类SCI接口),该类简称SpringSCI,该类不直接配置servlet容器,而是通过查找WebApplicationInitializer接口(用于web初始化)的实现类,间接配置servlet容器;
    4. Spring MVC提供基类 AbstractAnnotationConfigDispatcherServletInitializer,用于DispatcherServlet初始化(实现了WebApplicationInitializer接口),该基类既要完成WebApplicationInitializer接口中配置servlet容器的功能,又完成了配置MVC的功能,即同时配置了DispatcherServlet 和 ContextLoaderListener
    5. Spring提供的接口WebApplicationInitializer,用于配置servlet容器,并不是只用于配置MVC,可通过自定义二次开发继承WebApplicationInitializer,结合ServletRegistration.Dynamic,配置servlet容器,添加自定义的servlet、filter等,可完全替换掉web.xml
    6. 如果是在MVC项目中,想添加自定义的servlet、filter,可不用实现WebApplicationInitializer,直接只要重写 AbstractAnnotationConfigDispatcherServletInitializer 类的 getServletFilters() 方法就行了;不需要 mapping,因为会自动 mapping 到 DispatcherServlet 上,通过返回多个 filter,可以添加多个 filter。
  3. 总结3:spring  依据“java的SPI(Service Provider Interface)机制”和“servlet容器的SCI(ServletContainerInitializer)接口”,通过SpringServletContainerInitializer实现spring组件和servlet容器解耦,解耦后,spring组件可以直接使用spring提供的WebApplicationInitializer接口,实现类似SCI功能,通过实现WebApplicationInitializer,可以向servlet容器添加servlet,listener等。
    1. Servlet 3.0 规范和 Spring DispatcherServlet 配置
        在 Servlet 3.0 的环境中,容器会在 classpath 中寻找继承了 javax.servlet.ServletContainerInitializer 接口的类,用它来配置 servlet 容器。
        Spring 提供了一个继承这个接口的类 SpringServletContainerInitializer,在这个类中,它会寻找任何继承了 WebApplicationInitializer 接口的类并用其来配置 servlet 容器。
    2. Spring 3.2 提供了一个继承了 WebApplicationInitializer 接口的基类 AbstractAnnotationConfigDispatcherServletInitializer,用于配置Spring MVC项目。Spring 3.2 开始引入一个简易的 WebApplicationInitializer 实现类,这就是 AbstractAnnotationConfigDispatcherServletInitializer。
    3. 在AbstractAnnotationConfigDispatcherServletInitializer中,给我们留下了三个抽象方法要求我们去实现:

      • protected abstract String[] getServletMappings();    这个方法在AbstractDispatcherServletInitializer 中,这个方法可以将一个或多个路径映射到DispatcherServlet上,如果路径设置为“/”,则所有的请求都会由DispatcherServlet处理。
      • protected abstract Class<?>[] getRootConfigClasses();    这两个方法在AbstractAnnotationConfigDispatcherServletInitializer中
      • protected abstract Class<?>[] getServletConfigClasses();
    4. 在Spring MVC项目中
      1. 你的 servlet 配置类只需要继承 AbstractAnnotationConfigDispatcherServletInitializer,就会被发现而用于 servlet 容器的配置。
      2. AbstractAnnotationConfigDispatcherServletInitializer用于创建两种应用上下文:DispatcherServlet 创建的和拦截器 ContextLoaderListener 创建的上下文
      3. 在 AbstractAnnotationConfigDispatcherServletInitializer 中 DispatcherServlet 和 ContextLoaderListener 都会被创建,而基类中的方法就可用来创建不同的应用上下文:

        1. getServletConfigClasses():定义 DispatcherServlet 应用上下文中的 beans;

        2. getRootConfigClasses():定义拦截器 ContextLoaderListener 应用上下文中的 beans
      4. 示例
        1.   

          package spittr.config;
          import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;
          import spittr.web.WebConfig;
          public class SpitterWebInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
          @Override
          protected Class<?>[] getRootConfigClasses() {
          return new Class<?>[] { RootConfig.class };
          }
          @Override
          protected Class<?>[] getServletConfigClasses() {
          return new Class<?>[] { WebConfig.class };
          }
          @Override
          protected String[] getServletMappings() {
          return new String[] { "/" };
          }
          }
      5. 配置额外的 servlets 和 filters(非Bean,非DispatcherServlet 和 ContextLoaderListener中的元素)
        1. 如果需要定义额外的 servlets 或 filters,只需要创建额外的初始化类。在 Spring MVC 中可以通过继承 WebApplicationInitializer 接口来实现。
        2. 定义一个新的 servlet:
          
          package com.myapp.config;
          import javax.servlet.ServletContext;
          import javax.servlet.ServletException;
          import javax.servlet.ServletRegistration.Dynamic;
          import org.springframework.web.WebApplicationInitializer;
          import com.myapp.MyServlet;
          public class MyServletInitializer implements WebApplicationInitializer {
          @Override
          public void onStartup(ServletContext throws ServletException {
          Dynamic myServlet = servletContext.addServlet("myServlet", MyServlet.class);
          myServlet.addMapping("/custom/**");
          }
          } 定义 filters 和 listeners:
          @Override
          public void onStartup(ServletContext servletContext)
          throws ServletException {
          // 定义filter
          javax.servlet.FilterRegistration.Dynamic filter =
          servletContext.addFilter("myFilter", MyFilter.class);
          filter.addMappingForUrlPatterns(null, false, "/custom/*"); }
        3. 如果你需要为 DispatcherServlet 添加 filter 的话,就不用这么麻烦了,你只要重写 AbstractAnnotationConfigDispatcherServletInitializer 类的 getServletFilters() 方法就行了:

          @Override
          protected Filter[] getServletFilters() {
          return new Filter[] { new MyFilter() };
          }

          不需要 mapping,因为会自动 mapping 到 DispatcherServlet 上,通过返回多个 filter,可以添加多个 filter

    5. 参考:https://blog.csdn.net/w1196726224/article/details/52687324
    6. 参考:[Servlet3.0研究之ServletContainerInitializer接口 - 夫礼者的专栏 - CSDN博客: https://blog.csdn.net/lqzkcx3/article/details/78507169]
    7. 参考:[java中的SPI机制 - 司刚军的个人专栏 - CSDN博客: https://blog.csdn.net/sigangjun/article/details/79071850]
    8. 参考:[JavaSPI机制学习笔记 - 琴水玉 - 博客园: http://www.cnblogs.com/lovesqcc/p/5229353.html]
    9. 参考:[Servlet3.0研究之ServletContainerInitializer接口 - 夫礼者的专栏 - CSDN博客: https://blog.csdn.net/lqzkcx3/article/details/78507169]
    10. Service Provider Interface:

      java spi的具体使用如下  :

      当服务的提供者,提供了服务接口的一种实现之后,在jar包的META-INF/services/目录里同时创建一个以服务接口命名的文件。该文件里就是实现该服务接口的具体实现类。而当外部程序装配这个模块的时候,就能通过该jar包META-INF/services/里的配置文件找到具体的实现类名,并装载实例化,完成模块的注入。

      基于这样一个约定就能很好的找到服务接口的实现类,而不需要再代码里制定。

      jdk提供服务实现查找的一个工具类:java.util.ServiceLoader

  4. 使用JavaConfig普通web应用(非MVC)
    1. public class App {
      public static void main(String[] args) {
      ApplicationContext context = new AnnotationConfigApplicationContext(
      AppConfig.class);
      CustomerBo customer = (CustomerBo) context.getBean("customer");
      customer.printMsg("Hello 1");
      SchedulerBo scheduler = (SchedulerBo) context.getBean("scheduler");
      scheduler.printMsg("Hello 2");
      } } ############## import org.springframework.context.annotation.Configuration;
      import org.springframework.context.annotation.Import;
      @Configuration @Import({ CustomerConfig.class, SchedulerConfig.class }) public class AppConfig {
      } ############## @Configuration
      public class CustomerConfig {
      @Bean(name="customer")
      public CustomerBo customerBo(){
      return new CustomerBo();
      }
      } ##############
      public class SchedulerBo {
      public void printMsg(String msg) {
      System.out.println("SchedulerBo : " + msg); }
      }

Spring 梳理 - JavaConfig、SPI、SCI、SpringSCI、WebApplicationInitializer、AbstractAnnotationConfigDispatcherServletInitializer、WebMvcConfigurationSupport的更多相关文章

  1. Spring 梳理 - javaConfig在App和webApp中的应用

    package com.dxz.demo.configuration; import org.springframework.context.annotation.Configuration; @Co ...

  2. Spring 梳理 - JavaConfig实战(spring MVC)-原创

    目录结构 AppInitializer.java package com.jt; import org.springframework.web.servlet.support.AbstractAnno ...

  3. Spring 梳理 - 开启并配置 Spring MVC 的方法

    传统web.xm中配置两个上下文+两个context对应的xml+两个上下文bean分别手动配置 传统web.xm中配置两个上下文+两个context对应的xml+<mvc:annotation ...

  4. Spring 使用javaconfig配置

    除了使用xml,spring提供javaconfig配置,下面是简单的例子: 1.声明接口 /** * */ package com.junge.demo.spring.service; /** * ...

  5. Spring 梳理-MVC-配置DispatcherServet和ContextLoaderListener

    在使用JavaConfig时,AbstractAnnotationConfigDispatcherServletInitializer会自动注册 DispatcherServlet 和 Context ...

  6. 详细解说Java Spring的JavaConfig注解 【抄】

    抄自: http://www.techweb.com.cn/network/system/2016-01-05/2252188.shtml @RestController spring4为了更方便的支 ...

  7. Java Spring的 JavaConfig 注解

    序 传统spring一般都是基于xml配置的,不过后来新增了许多JavaConfig的注解.特别是springboot,基本都是清一色的java config,不了解一下,还真是不适应.这里备注一下. ...

  8. 使用Spring的JavaConfig 和 @Autowired注解与自动装配

    1 JavaConfig  配置方法 之前我们都是在xml文件中定义bean的,比如: 1 2 3 4 5 6 7 8 <beans xmlns="http://www.springf ...

  9. Spring MVC 零配置 / Spring MVC JavaConfig

    1. Spring MVC的核心就是DispatcherServlet类,Spring MVC处理请求的流程如下图所示: 2. Spring MVC中典型的上下文层次 当我们初始化一个Dispatch ...

随机推荐

  1. 替代Flume——Kafka Connect简介

    我们知道过去对于Kafka的定义是分布式,分区化的,带备份机制的日志提交服务.也就是一个分布式的消息队列,这也是他最常见的用法.但是Kafka不止于此,打开最新的官网. 我们看到Kafka最新的定义是 ...

  2. Vmware启动ubuntu 出现错误。

    Vmware启动ubuntu 出现错误“以独占方式锁定此配置文件失败. 可能其它正在运行VMware进程在使用此配置文件”. 在网上查找了很多方法,法(1)试过在启动任务管理器中“结束与VMware有 ...

  3. phpcms v9.6.0任意文件上传漏洞(CVE-2018-14399)

    phpcms v9.6.0任意文件上传漏洞(CVE-2018-14399) 一.漏洞描述 PHPCMS 9.6.0版本中的libs/classes/attachment.class.php文件存在漏洞 ...

  4. Java中指令重排

    /** * 指令重排:代码执行顺序与预期不一致 (发生在前后行代码无联系时) * 目的:提高性能 * */ public class HappenBefore { private static int ...

  5. 为什么有了Compose和Swarm,还会有Kubernetes的出现?

    一.k8s设计思想更先进 k8s的主要设置思想,是从更宏观的角度,以统一的方式来定义任务之间的各种关系 1.k8s的核心功能图 2.k8s的全局架构图 kube-apiserver:API服务 Kub ...

  6. HDU-2018多校7th-1011-Swordsman 附杜教fread代码

    HDU-6396 题意: 背景是打怪升级的故事,有k个不同属性的初始的能力值,每只怪物也有相同个数的能力值,你只能放倒k个能力值都比怪物大的,每放倒一个怪物,都可以得到相应的k个能力值. 思路: 根据 ...

  7. HDU 6394 Tree 分块 || lct

    Tree 题意: 给你一颗树, 每一个节点都有一个权值, 如果一个石头落在某个节点上, 他就会往上跳这个的点的权值步. 现在有2种操作, 1 把一个石头放在 x 的位置 询问有跳几次才跳出这棵树, 2 ...

  8. Codeforces 832 D Misha, Grisha and Underground

    Misha, Grisha and Underground 题意:Misha 和 Grisha 是2个很喜欢恶作剧的孩子, 每天早上 Misha 会从地铁站 s 通过最短的路到达地铁站 f, 并且在每 ...

  9. Codeforces Round #381 (Div. 2) C. Alyona and mex(无语)

    题目链接 http://codeforces.com/contest/740/problem/C 题意:有一串数字,给你m个区间求每一个区间内不含有的最小的数,输出全部中最小的那个尽量使得这个最小值最 ...

  10. pyppeteer的使用

    pyppeteer的使用 安装 属于第三方模块进行安装. pip install pyppeteer 在Linux中,如果权限不够则加上. sudo pip install pyppeteer 使用 ...