@EnableWebMvc 与 @EnableAutoConfiguration 的关系
来源:互联网 发布:mac os x 10.9.5 编辑:程序博客网 时间:2024/06/05 10:47
先讲自动配置:@EnableAutoConfiguration,引入两个 JAVA 类
@AutoConfigurationPackage@Import(EnableAutoConfigurationImportSelector.class)public @interface EnableAutoConfiguration {}
@Import(AutoConfigurationPackages.Registrar.class)public @interface AutoConfigurationPackage {}
目前还不清楚这两个类的原理,但是可以知道的是,Spring 通过这两个类查找所有 JAR 包的 classpath:META-INF/spring.factories,找到 spring-boot-autoconfigure-xxx.jar 的 META-INF/spring.factories,并包含如下内容
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\......org.springframework.boot.autoconfigure.web.WebMvcAutoConfiguration,\......
由此,Spring 加载了 WebMvc 的自动配置类
@Configuration@ConditionalOnWebApplication@ConditionalOnClass({ Servlet.class, DispatcherServlet.class, WebMvcConfigurerAdapter.class })@ConditionalOnMissingBean(WebMvcConfigurationSupport.class)@AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE + 10)@AutoConfigureAfter({ DispatcherServletAutoConfiguration.class, ValidationAutoConfiguration.class })public class WebMvcAutoConfiguration { //......}
值得注意的是 @ConditionalOnMissingBean(WebMvcConfigurationSupport.class),记住这个注解条件,请看以下 Spring 继承体系
记住这个继承关系,接着再来看 @EnableWebMvc,它引入了一个 Spring JavaConfig 类
@Import(DelegatingWebMvcConfiguration.class)public @interface EnableWebMvc {}
Spring 会加载 DelegatingWebMvcConfiguration.class 这个配置类,由之前的继承体系我们得知,它是 WebMvcConfigurationSupport 的子类,根据先前看到的自动配置的注解条件:只有当 WebMvcConfigurationSupport 这个 Bean 不存在时才加载 WebMvc 的自动配置类,否则忽略;换句话说,DelegatingWebMvcConfiguration.class 的加载取消了 WebMvc 的自动配置,也可以说 @EnableWebMvc 强制使用了另一套配置,而非 @EnableAutoConfiguration 指引的自动配置
呢么 @EnableWebMvc 有什么好处么?当然有,WebMvcConfigurationSupport(DelegatingWebMvcConfiguration 的父类) 定义了一套创建 Bean 的标准化流程,例如 RequestMappingHandlerMapping、resourceHandlerMapping、HttpMessageConverter 等等,并通过 “模板方法模式” 将其过程开放给子类,以 HttpMessageConverter 为例,请看 WebMvcConfigurationSupport 的 getMessageConverters()
protected final List<HttpMessageConverter<?>> getMessageConverters() { if (this.messageConverters == null) { this.messageConverters = new ArrayList<HttpMessageConverter<?>>(); //这个就是模板方法,是抽象方法,必须由子类重写 configureMessageConverters(this.messageConverters); if (this.messageConverters.isEmpty()) { //如果用户未定义任何 messageConverters,则进行默认初始化 //默认初始化包含了 ByteArrayHttpMessageConverter、ResourceHttpMessageConverter 等 addDefaultHttpMessageConverters(this.messageConverters); } //钩子方法 extendMessageConverters(this.messageConverters); } return this.messageConverters;}//模板方法是抽象的,必须由子类重写protected void configureMessageConverters(List<HttpMessageConverter<?>> converters) {}
可以看到,这就是创建 MessageConverters 的标准化流程,再看 @EnableWebMvc 导入的 DelegatingWebMvcConfiguration(即 WebMvcConfigurationSupport 子类)是如何重写 该模板方法的
@Overrideprotected void configureMessageConverters(List<HttpMessageConverter<?>> converters) { this.configurers.configureMessageConverters(converters);}
可以看到,它直接把所有的 HttpMessageConverter 交给 this.configurers 进行处理,无论是添加还是删除,是修改还是无所作为,这都是可行的,注意,这里暗示了我们开发者介入的契机,呢么 this.configurers 又是什么呢
private final WebMvcConfigurerComposite configurers = new WebMvcConfigurerComposite();@Autowired(required = false)public void setConfigurers(List<WebMvcConfigurer> configurers) { if (!CollectionUtils.isEmpty(configurers)) { this.configurers.addWebMvcConfigurers(configurers); }}
简单来讲,WebMvcConfigurerComposite 就是一个容纳许多 WebMvcConfigurer 的容器,Spring 通过 @Autowired 来自动注入所有的 WebMvcConfigurer,并全部添加进容器里;这意味着,我们可以定义任意多的 WebMvcConfigurer,它们全部都会被纳入容器中,并依次接受 Spring 分派所有的 HttpMessageConverter 来处理,我们可以在处理中添加我们自己想要的 HttpMessageConverter,再来看一次该模板方法代码
@Overrideprotected void configureMessageConverters(List<HttpMessageConverter<?>> converters) { this.configurers.configureMessageConverters(converters);}
configurers 只是个容器,这里可能会被误导,查看其源码
@Overridepublic void configureMessageConverters(List<HttpMessageConverter<?>> converters) { for (WebMvcConfigurer delegate : this.delegates) { delegate.configureMessageConverters(converters); }}
很明显,它依次调用容器中所有的 WebMvcConfigurer 的 configureMessageConverters(),所以我们要做的是:定义一个或多个 Bean 继承 WebMvcConfigurer 并重写 configureMessageConverters(),在这里面添加我们想要的 HttpMessageConverter,然后等着被自动注入,被模板方法依次调用,我们的奇思妙想就成功了,注意,一般只需要重写很少的抽象方法,因此推荐继承 WebMvcConfigurer 的子类 WebMvcConfigurerAdapter,并重写有需要的一个或几个方法
@Configurationpublic class WebMvcConfigurer extends WebMvcConfigurerAdapter { // 自定义 JSON 转换工具 @Override public void configureMessageConverters(List<HttpMessageConverter<?>> converters) { converters.add(fastJsonHttpMessageConverterEx()); super.configureMessageConverters(converters); } @Bean public FastJsonHttpMessageConverterEx fastJsonHttpMessageConverterEx() { return new FastJsonHttpMessageConverterEx(); }}
注意 @Configuration 是必要的,只有这样才能将其装配成 Bean,进而被 @Autowired 自动注入
- @EnableWebMvc 与 @EnableAutoConfiguration 的关系
- @EnableWebMVC
- @EnableAutoConfiguration
- @EnableAutoConfiguration
- EnableAutoConfiguration注解的工作原理
- Spring Boot的@SpringBootApplication、@EnableAutoConfiguration、@ComponentScan注解
- Spring @EnableWebMvc
- @SpringBootApplication 相当于 @Configuration、@EnableAutoConfiguration 、 @ComponentScan 三个的作用
- @EnableAutoConfiguration注解
- @EnableWebMvc 、WebMvcConfigurationSupport和WebMvcConfigurationAdapter
- 解析@EnableWebMvc 、WebMvcConfigurationSupport和WebMvcConfigurationAdapter
- SpringBoot @EnableAutoConfiguration原理
- 深入SpringBoot:自定义EnableAutoConfiguration
- @EnableAutoConfiguration和@SpringbootApplication注解
- 关系型数据库与Nosql的关系
- 劳务关系与劳动关系的区别
- 关系与非关系数据库的比较
- RPC与Socket的关系,RPC与RMI的关系!
- DynaProperty、DynaBean及DynaClass类的使用
- ckediter图片内联属性style笨而有效的去除方法
- POI技术实现EXCEL的导入导出
- Driver 分层的思想 -- Linux Kernel 内核实现欣赏
- Carbide编辑CP代码中的环境配置及编译
- @EnableWebMvc 与 @EnableAutoConfiguration 的关系
- EU4-33: Sloving an employee problem
- 浅谈树链剖分
- Java中Class类与RTTI
- 手机的唯一识别符
- 第17课
- POJ 1273 Drainage Ditches
- Angular 2基础(一) 环境搭建
- matlab 怎么在直角坐标系中添加最值得数值