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. HDU 6059

    题意略. 思路:我们要想令 A[i] ^ A[j] < A[j] ^ A[k](i < j < k),由于A[i]和A[k]都要 ^ A[j],所以我们只需研究一下i,k这两个数之间 ...

  2. 学习笔记之Java队列Queue中offer/add函数,poll/remove函数,peek/element函数的区别

    队列是一种特殊的线性表,它只允许在表的前端进行删除操作,而在表的后端进行插入操作. LinkedList类实现了Queue接口,因此我们可以把LinkedList当成Queue来用. Java中Que ...

  3. JavaScript 数据结构与算法之美 - 冒泡排序、插入排序、选择排序

    1. 前言 算法为王. 想学好前端,先练好内功,只有内功深厚者,前端之路才会走得更远. 笔者写的 JavaScript 数据结构与算法之美 系列用的语言是 JavaScript ,旨在入门数据结构与算 ...

  4. volatile底层实现原理

    前言 当共享变量被声明为volatile后,对这个变量的读/写操作都会很特别,下面我们就揭开volatile的神秘面纱. 1.volatile的内存语义 1.1 volatile的特性 一个volat ...

  5. js 取两位小数

    var totalPrice = (product.unitPrice * product.nums).toFixed(2);

  6. 掀起你的盖头来:浅谈项目管理办公室(PMO)

    [提示]本文为“分享:<PMBOOK>读书笔记系列”由傻瓜(来自人人都是产品经理6群)编写. 之前与大家一定对项目.项目管理.项目集.项目组合等知识进行了简单的学习,如果有不太清楚和不太明 ...

  7. Installing the JMeter CA certificate for HTTPS recording

    参考: http://jmeter.apache.org/usermanual/component_reference.html#HTTP(S)_Test_Script_Recorder User m ...

  8. 利用python定位网页上的元素

    1. 想对网页上的元素进行操作,首先需要定位到元素. 以百度首页为例: 输入以下代码,打开百度首页: # coding = gbk from selenium import webdriver chr ...

  9. 解决homebrew下install时出现的问题

    在homebrew下install   influxdb时出现error: Error: Failure while executing: git config --local --replace-a ...

  10. 全栈开发博客系统(nodejs+vuejs+mongodb)

    本篇文章将会介绍如何使用nodejs+vuejs构建个人博客. 主要分三部分内容: 环境准备 博客后端管理系统(admin) 后端服务(主要提供admin及web端接口) 博客前端展示(web) 环境 ...