在SpringBoot中可以通过以下两种方式来完成自定义WebMvc的配置:
(1)继承WebMvcConfigurationSupport类
(2)实现WebMvcConfigurer接口
通过这两种方式完成的WebMvc配置存在差异,本文将对此作简单说明与区分。
一.继承WebMvcConfigurationSupport类
1.WebMvcConfigurationSupport是一个用于实现自定义WebMvc配置的类,里面提供了如添加自定义拦截器、消息转换器等方法,同时对于部分方法具有默认实现。
2.WebMvcConfigurationSupport中很多方法都被打上@Bean注解,这代表这些方法提供的对象将会交给IOC容器管理。但是WebMvcConfigurationSupport这个类却并未被打上@Configuration注解
因此在使用继承WebMvcConfigurationSupport的方式来完成自定义WebMvc配置时,需要手动给打上@Configuration注解,这样WebMvcConfigurationSupport中的@Bean方法才能生效。
3. SpringBoot对SpringMvc已经做了自动配置。默认情况下,SpringBoot会使用自己的WebMvc配置类WebMvcAutoConfiguration,而该类实现自动配置的关键在于其内部类EnableWebMvcConfiguration
可以看到作为WebMvcAutoConfiguration内部类的EnableWebMvcConfiguration又是DelegatingWebMvcConfiguration这个类的子类,那么我们再到DelegatingWebMvcConfiguration这个类内部看一下
可以看到DelegatingWebMvcConfiguration继承了WebMvcConfigurationSupport。
在Spring框架中,我们可以通过继承WebMvcConfigurationSupport类的方式来实现自定义WebMvc配置,而SpringBoot底层正是通过这种方式来完成自己的WebMvc配置。也就是说我们在SpringBoot中,实际上已经在使用SpringBoot为我们提供的,不同于Spring框架默认配置的WebMvc配置。
4.如果自己使用继承WebMvcConfigurationSupport的方式来实现自定义WebMvc配置,则会覆盖SpringBoot提供的WebMvc配置。
(1)我们在SpringBoot的WebMvc配置类WebMvcAutoConfiguration类上可以看到这一行注解:@ConditionalOnMissingBean({WebMvcConfigurationSupport.class})
该注解的意思是:在SpringBoot实现自动装配时,如果IOC容器中不存在类型为WebMvcConfigurationSupport的bean,才会将这个WebMvcAutoConfiguration实例化。
(2)而如果我们使用继承WebMvcConfigurationSupport类的方式来实现自定义WebMvc配置,则在自动装配时,将导致WebMvcAutoConfiguration无法实例化,其内部初始化配置将全部无法实例化,也就是说SpringBoot提供的WebMvc配置失效;取而代之的,我们自己实现的WebMvcAutoConfiguration类将作为全部WebMvc配置的源头。
(3)如果我们采用这种方式实现WebMvc配置,且在子类中只重写自己需要拓展的功能方法,则其他方法将采用WebMvcConfigurationSupport的默认方法,其默认方法有的是空方法,而有的给了默认实现。但需要注意的是,WebMvcConfigurationSupport那些给了默认实现的方法,与SpringBoot的WebMvc配置类WebMvcAutoConfiguration自己实现的方法是不一样的。我们如果继承WebMvcConfigurationSupport,而不重写其方法,那么我们就是在使用Spring提供的WebMvc配置,而不是SpringBoot提供的WebMvc配置。
(4)因此,使用继承WebMvcConfigurationSupport类实现自定义WebMvc配置这种方式的缺点是显而易见的——我们将为了拓展部分WebMvc配置,而抛弃全部SpringBoot已经为我们实现的便捷的WebMvc配置。
二.实现WebMvcConfigurer接口
1.WebMvcConfigurer是一个用于实现自定义WebMvc配置的接口,里面同样提供了如添加自定义拦截器、消息转换器等方法,且都是默认为空实现的方法。
2.由于WebMvcConfigurer接口也未被打上@Configuration注解,因此要手动给自编写的实现类打上@Configuration注解。
3.使用实现WebMvcConfigurer接口的方式来实现自定义WebMvc配置,并不会覆盖SpringBoot自己实现的配置。
(1)上文提到,只有在IOC中已经有类型为WebMvcConfigurationSupport的bean的时候,SpringBoot的WebMvc配置类WebMvcAutoConfiguration才不会生效。
(2)而如果我们使用实现WebMvcConfigurer接口的方式自定义WebMvc配置,则WebMvcAutoConfiguration可以被实例化,SpringBoot自己配置的WebMvc成功生效。
(3)而如果在实现WebMvcConfigurer接口时,我们自己实现的方法在SpringBoot的WebMvcAutoConfiguration中也被实现了,则会合并而不是覆盖。这说明了实现WebMvcConfigurer接口是一种增量式的配置方式:
当我们实现WebMvcConfigurer接口并重写其中的某个方法时,实际上是在提供额外的配置或定制逻辑,这些配置或逻辑将与SpringBoot的默认配置合并。SpringBoot会先加载其默认的自动配置,然后应用你在WebMvcConfigurer中定义的自定义配置。
4.继承WebMvcConfigurationSupport与实现WebMvcConfigurer是不同的配置逻辑
(1)继承WebMvcConfigurationSupport类是抛弃所有SpringBoot提供的WebMvc配置,全部由自己实现。
(2)实现WebMvcConfigurer接口是在保留SpringBoot提供的WebMvc配置的基础上,添加自己要拓展的配置。
(3)因此,实际开发中更推荐使用实现WebMvcConfigurer接口的方式来完成自定义WebMvc配置。