Spring 梳理 - JavaConfig、SPI、SCI、SpringSCI、WebApplicationInitializer、AbstractAnnotationConfigDispatcherServletInitializer、WebMvcConfigurationSupport
- 总结1:
- SCI:Servlet容器(Tomcat)提供的初始化Servlet容器本身的接口,可替换web.xml
- SpringSCI:SpringServletContainerInitializer,Srping提供的SCI的一个实现,起到中转桥接作用,桥接到 WebApplicationInitializer 接口上
- WebApplicationInitializer :可以自定义配置servlet、listener,进而可以通过代码手动控制两个上下文的创建过程(参考:基于xml 参考:支持注解);只能创建上线文但不能配置上下文详细内容,但可以指定上下文配置文件的路径或配置类的类路径
AbstractAnnotationConfigDispatcherServletInitializer
:将两个上下文自动已创建好,已创建好的上下文的类型都是支持注解的;手动继承后只需要指定两个上下文配置类路径即可。- WebMvcConfigurer:
WebMvcConfigurationAdapter已经废弃,最好用implements WebMvcConfigurer代替
@Configuration
public class MyConfig implements WebMvcConfigurer { }如果使用继承,WebMvcConfigurationSupport,DelegatingWebMvcConfiguration,或者使用@EnableWebMvc
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 typeWebMvcConfigurer
but without@EnableWebMvc
. If you wish to provide custom instances ofRequestMappingHandlerMapping
,RequestMappingHandlerAdapter
, orExceptionHandlerExceptionResolver
, you can declare aWebMvcRegistrationsAdapter
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:
- java提供SPI,用于加载指定接口的 特定实现类
- servlet容器提供SCI接口,用于配置servlet容器初始化;这个过程使用了java的SPI机制;类似Logfactory的工作原理
- Spring提供SpringServletContainerInitializer类(该类实现类SCI接口),该类简称SpringSCI,该类不直接配置servlet容器,而是通过查找WebApplicationInitializer接口(用于web初始化)的实现类,间接配置servlet容器;
- Spring MVC提供基类 AbstractAnnotationConfigDispatcherServletInitializer,用于DispatcherServlet初始化(实现了WebApplicationInitializer接口),该基类既要完成WebApplicationInitializer接口中配置servlet容器的功能,又完成了配置MVC的功能,即同时配置了DispatcherServlet 和 ContextLoaderListener
- Spring提供的接口
WebApplicationInitializer,用于配置servlet容器,并不是只用于配置MVC
,可通过自定义二次开发继承WebApplicationInitializer,结合ServletRegistration.Dynamic
,配置servlet容器,添加自定义的servlet、filter等,可完全替换掉web.xml - 如果是在MVC项目中,想添加自定义的servlet、filter,可不用实现
WebApplicationInitializer
,直接只要重写AbstractAnnotationConfigDispatcherServletInitializer
类的getServletFilters()
方法就行了;不需要 mapping,因为会自动 mapping 到DispatcherServlet
上,通过返回多个 filter,可以添加多个 filter。
- 总结3:spring 依据“java的SPI(Service Provider Interface)机制”和“servlet容器的SCI(ServletContainerInitializer)接口”,通过SpringServletContainerInitializer实现spring组件和servlet容器解耦,解耦后,spring组件可以直接使用spring提供的WebApplicationInitializer接口,实现类似SCI功能,通过实现WebApplicationInitializer,可以向servlet容器添加servlet,listener等。
- Servlet 3.0 规范和 Spring DispatcherServlet 配置
在 Servlet 3.0 的环境中,容器会在 classpath 中寻找继承了 javax.servlet.ServletContainerInitializer 接口的类,用它来配置 servlet 容器。
Spring 提供了一个继承这个接口的类 SpringServletContainerInitializer,在这个类中,它会寻找任何继承了 WebApplicationInitializer 接口的类并用其来配置 servlet 容器。 - Spring 3.2 提供了一个继承了 WebApplicationInitializer 接口的基类 AbstractAnnotationConfigDispatcherServletInitializer,用于配置Spring MVC项目。Spring 3.2 开始引入一个简易的 WebApplicationInitializer 实现类,这就是 AbstractAnnotationConfigDispatcherServletInitializer。
在AbstractAnnotationConfigDispatcherServletInitializer中,给我们留下了三个抽象方法要求我们去实现:
- protected abstract String[] getServletMappings(); 这个方法在AbstractDispatcherServletInitializer 中,这个方法可以将一个或多个路径映射到DispatcherServlet上,如果路径设置为“/”,则所有的请求都会由DispatcherServlet处理。
- protected abstract Class<?>[] getRootConfigClasses(); 这两个方法在AbstractAnnotationConfigDispatcherServletInitializer中
- protected abstract Class<?>[] getServletConfigClasses();
- 在Spring MVC项目中
- 你的 servlet 配置类只需要继承 AbstractAnnotationConfigDispatcherServletInitializer,就会被发现而用于 servlet 容器的配置。
- AbstractAnnotationConfigDispatcherServletInitializer用于创建两种应用上下文:
DispatcherServlet
创建的和拦截器ContextLoaderListener
创建的上下文 在 AbstractAnnotationConfigDispatcherServletInitializer 中 DispatcherServlet 和 ContextLoaderListener 都会被创建,而基类中的方法就可用来创建不同的应用上下文:
getServletConfigClasses():定义 DispatcherServlet 应用上下文中的 beans;
- getRootConfigClasses():定义拦截器 ContextLoaderListener 应用上下文中的 beans
- 示例
-
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[] { "/" };
}
}
-
- 配置额外的 servlets 和 filters(非Bean,非DispatcherServlet 和 ContextLoaderListener中的元素)
- 如果需要定义额外的 servlets 或 filters,只需要创建额外的初始化类。在 Spring MVC 中可以通过继承
WebApplicationInitializer
接口来实现。 定义一个新的 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/*"); }如果你需要为 DispatcherServlet 添加 filter 的话,就不用这么麻烦了,你只要重写 AbstractAnnotationConfigDispatcherServletInitializer 类的 getServletFilters() 方法就行了:
@Override
protected Filter[] getServletFilters() {
return new Filter[] { new MyFilter() };
}不需要 mapping,因为会自动 mapping 到 DispatcherServlet 上,通过返回多个 filter,可以添加多个 filter
- 如果需要定义额外的 servlets 或 filters,只需要创建额外的初始化类。在 Spring MVC 中可以通过继承
- 参考:https://blog.csdn.net/w1196726224/article/details/52687324
- 参考:[Servlet3.0研究之ServletContainerInitializer接口 - 夫礼者的专栏 - CSDN博客: https://blog.csdn.net/lqzkcx3/article/details/78507169]
- 参考:[java中的SPI机制 - 司刚军的个人专栏 - CSDN博客: https://blog.csdn.net/sigangjun/article/details/79071850]
- 参考:[JavaSPI机制学习笔记 - 琴水玉 - 博客园: http://www.cnblogs.com/lovesqcc/p/5229353.html]
- 参考:[Servlet3.0研究之ServletContainerInitializer接口 - 夫礼者的专栏 - CSDN博客: https://blog.csdn.net/lqzkcx3/article/details/78507169]
- Service Provider Interface:
java spi的具体使用如下 :
当服务的提供者,提供了服务接口的一种实现之后,在jar包的META-INF/services/目录里同时创建一个以服务接口命名的文件。该文件里就是实现该服务接口的具体实现类。而当外部程序装配这个模块的时候,就能通过该jar包META-INF/services/里的配置文件找到具体的实现类名,并装载实例化,完成模块的注入。
基于这样一个约定就能很好的找到服务接口的实现类,而不需要再代码里制定。
jdk提供服务实现查找的一个工具类:java.util.ServiceLoader
- Servlet 3.0 规范和 Spring DispatcherServlet 配置
- 使用JavaConfig普通web应用(非MVC)
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的更多相关文章
- Spring 梳理 - javaConfig在App和webApp中的应用
package com.dxz.demo.configuration; import org.springframework.context.annotation.Configuration; @Co ...
- Spring 梳理 - JavaConfig实战(spring MVC)-原创
目录结构 AppInitializer.java package com.jt; import org.springframework.web.servlet.support.AbstractAnno ...
- Spring 梳理 - 开启并配置 Spring MVC 的方法
传统web.xm中配置两个上下文+两个context对应的xml+两个上下文bean分别手动配置 传统web.xm中配置两个上下文+两个context对应的xml+<mvc:annotation ...
- Spring 使用javaconfig配置
除了使用xml,spring提供javaconfig配置,下面是简单的例子: 1.声明接口 /** * */ package com.junge.demo.spring.service; /** * ...
- Spring 梳理-MVC-配置DispatcherServet和ContextLoaderListener
在使用JavaConfig时,AbstractAnnotationConfigDispatcherServletInitializer会自动注册 DispatcherServlet 和 Context ...
- 详细解说Java Spring的JavaConfig注解 【抄】
抄自: http://www.techweb.com.cn/network/system/2016-01-05/2252188.shtml @RestController spring4为了更方便的支 ...
- Java Spring的 JavaConfig 注解
序 传统spring一般都是基于xml配置的,不过后来新增了许多JavaConfig的注解.特别是springboot,基本都是清一色的java config,不了解一下,还真是不适应.这里备注一下. ...
- 使用Spring的JavaConfig 和 @Autowired注解与自动装配
1 JavaConfig 配置方法 之前我们都是在xml文件中定义bean的,比如: 1 2 3 4 5 6 7 8 <beans xmlns="http://www.springf ...
- Spring MVC 零配置 / Spring MVC JavaConfig
1. Spring MVC的核心就是DispatcherServlet类,Spring MVC处理请求的流程如下图所示: 2. Spring MVC中典型的上下文层次 当我们初始化一个Dispatch ...
随机推荐
- HDU 6059
题意略. 思路:我们要想令 A[i] ^ A[j] < A[j] ^ A[k](i < j < k),由于A[i]和A[k]都要 ^ A[j],所以我们只需研究一下i,k这两个数之间 ...
- 学习笔记之Java队列Queue中offer/add函数,poll/remove函数,peek/element函数的区别
队列是一种特殊的线性表,它只允许在表的前端进行删除操作,而在表的后端进行插入操作. LinkedList类实现了Queue接口,因此我们可以把LinkedList当成Queue来用. Java中Que ...
- JavaScript 数据结构与算法之美 - 冒泡排序、插入排序、选择排序
1. 前言 算法为王. 想学好前端,先练好内功,只有内功深厚者,前端之路才会走得更远. 笔者写的 JavaScript 数据结构与算法之美 系列用的语言是 JavaScript ,旨在入门数据结构与算 ...
- volatile底层实现原理
前言 当共享变量被声明为volatile后,对这个变量的读/写操作都会很特别,下面我们就揭开volatile的神秘面纱. 1.volatile的内存语义 1.1 volatile的特性 一个volat ...
- js 取两位小数
var totalPrice = (product.unitPrice * product.nums).toFixed(2);
- 掀起你的盖头来:浅谈项目管理办公室(PMO)
[提示]本文为“分享:<PMBOOK>读书笔记系列”由傻瓜(来自人人都是产品经理6群)编写. 之前与大家一定对项目.项目管理.项目集.项目组合等知识进行了简单的学习,如果有不太清楚和不太明 ...
- Installing the JMeter CA certificate for HTTPS recording
参考: http://jmeter.apache.org/usermanual/component_reference.html#HTTP(S)_Test_Script_Recorder User m ...
- 利用python定位网页上的元素
1. 想对网页上的元素进行操作,首先需要定位到元素. 以百度首页为例: 输入以下代码,打开百度首页: # coding = gbk from selenium import webdriver chr ...
- 解决homebrew下install时出现的问题
在homebrew下install influxdb时出现error: Error: Failure while executing: git config --local --replace-a ...
- 全栈开发博客系统(nodejs+vuejs+mongodb)
本篇文章将会介绍如何使用nodejs+vuejs构建个人博客. 主要分三部分内容: 环境准备 博客后端管理系统(admin) 后端服务(主要提供admin及web端接口) 博客前端展示(web) 环境 ...