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 1517

    题意略. 思路: 我们分别来考虑n取到的各个区间,从而发现其中的规律: [2,9] 明显 Stan 必胜. 但是当n = 9 + 1时,Stan无论如何也不能取胜,并且此时,假设 Stan 取值 x ...

  2. 【原创】ARMv8 MMU及Linux页表映射

    背景 Read the fucking source code! --By 鲁迅 A picture is worth a thousand words. --By 高尔基 说明: Kernel版本: ...

  3. 【原创】Linux cpuidle framework

    背景 Read the fucking source code! --By 鲁迅 A picture is worth a thousand words. --By 高尔基 说明: Kernel版本: ...

  4. MSIL实用指南-生成break和continue

    break和continue本质都是标签的跳转

  5. 如何使用有道云笔记的Markdown----初级版?

    我一般整理笔记用的是用有道云笔记,在这里,Markdown怎么用? 什么是Markdown?Markdown是一种轻量级的「标记语言」,通常为程序员群体所用,目前它已是全球最大的技术分享网站 GitH ...

  6. 2019-04-23-Python爬取有声小说

    目录 Python爬取有声小说 摘要 1.获取下载链接 2.分析规律,循环爬取 3.保存到本地,批量命名 4.界面设计 5.效果展示 Python爬取有声小说 通过python爬取网站的资源,实现批量 ...

  7. 分享一个赚钱方法:用趣分类app在家轻松赚钱

    什么是趣分类 近期,垃圾分类是社会各界和广大市民关心的一个热门话题,随着垃圾分类工作的推进,各地都掀起学习垃圾分类的热潮.为了我们的美好生活,打响"垃圾分类"这场硬仗刻不容缓.据了 ...

  8. CodeForces 948B Primal Sport

    Primal Sport 题意:2个人玩游戏, 每次轮到一个人选择一个比当前值小的素数, 然后在找到比素数的倍数中最小的并且不小于当前数的一个数. 现在这个游戏玩了2轮, 现在想找到最小的那个起点X0 ...

  9. UVA - 10480 Sabotage 最小割,输出割法

    UVA - 10480 Sabotage 题意:现在有n个城市,m条路,现在要把整个图分成2部分,编号1,2的城市分成在一部分中,拆开每条路都需要花费,现在问达成目标的花费最少要隔开那几条路. 题解: ...

  10. Jmeter基础教程图文版(二)- 核心组件

    ⚪Jmeter Apache JMeter 是 Apache 组织开发的基于 Java 的压力测试工具.用于对软件做压力测试,它最初被设计用于 Web 应用测试,但后来扩展到其他测试领域. 它可以用于 ...