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. unity_小功能实现(客户端相互通信功能)

    服务器端:在VS中新建项目,用于服务器的搭建 using System;using System.Collections.Generic;     using System.Net.Sockets;u ...

  2. 10_switch语句的使用

    /* switch 语句和c语言的用法不同 1.go语句是默认添加break语句的,但c不是默认的 2.go语句添加一个fallthrough语句,可以顺序执行接下来的结构 3.switch在关键词后 ...

  3. Linux之Shell编程(14)

    变量: 定义变量的规则: 1)变量名可以由字母.数字和下划线组成,但不能以数字开头 2)等号两侧不能有空格 3)变量名一般习惯大写 将命令的返回值赋值给变量: 1)使用``将命令括起来 2)使用$() ...

  4. javascript语言精粹数组篇之Array的方法注意事项

    本文并没有详细列出Array方法详解,本文侧重点在于使用Array编程时候要注意的问题.1.Array.concat var o = {name:"Gavin"}; var a1 ...

  5. 那些让你觉得自己是个傻B的题目集锦(大神的降维打击合集)

    一起过来排好队,进来挨打 1.Leetcode tag-LinkList 109.convert sorted list to binary search tree 2Leetcode tag-Arr ...

  6. hdu 5898 odd-even number(数位dp)

    Problem Description For a number,if the length of continuous odd digits is even and the length of co ...

  7. POJ 1390 Blocks (区间DP) 题解

    题意 t组数据,每组数据有n个方块,给出它们的颜色,每次消去的得分为相同颜色块个数的平方(要求连续),求最大得分. 首先看到这题我们发现我们要把大块尽可能放在一起才会有最大收益,我们要将相同颜色块合在 ...

  8. Node基础-CommonJS模块化规范

    1.在本地项目中基于NPM/YARN安装第三方模块 第一步:在本地项目中创建一个"package.json"的文件 作用:把当前项目所有依赖的第三方模块信息(包含:模块名称以及版本 ...

  9. maven学习笔记(超详细总结)

    目录 项目管理利器--maven 第1章 maven概述 1-1 项目管理利器-maven简介 1.1.1 什么是maven 1.1.2 什么是依赖管理 1.1.3 传统项目的依赖管理 1.1.4 m ...

  10. 一个例子明白 javascript 中 for 与 for in 的区别

    var arr = new Array(); arr["a"] = "aa"; arr["b"] = "bb"; arr ...