相信大家在使用springMVC的时候,都或多或少需要对它进行配置,不管使用xml的方式还是Java注解的方式。今天我们就从springMVC的配置上,谈一谈其中一个很重要的设计模式:组合模式。
定义
惯例我们先来看一看组合模式的定义:组合模式,将对象组合成树形结构以表示“部分-整体”的层次结构,组合模式使得用户对单个对象和组合对象的使用具有一致性。通俗的来说,就是讲一系列的对象组合在一个整体的对象中,用户在对这个组合对象操作使用时就能跟操作一个对象一样。
从配置springMVC开始看
我们在使用Java注解对springMVC进行配置时,通常是使用以下方式:
// 自己的配置通过继承自WebMvcConfigurerAdapter类,重写方法来进行springMVC的配置,这边WebMvcConfigurerAdapter是WebMvcConfigurer的一个适配类,提供了一系列可配置的接口方法
public class MyConfiguration extends WebMvcConfigurerAdapter {
@Override
public void addFormatters(FormatterRegistry formatterRegistry) {
formatterRegistry.addConverter(new MyConverter());
}
@Override
public void configureMessageConverters(List<HttpMessageConverter> converters) {
converters.add(new MyHttpMessageConverter());
}
// More overridden methods ...
}
那么springMVC是怎么探测到你这些重写的方法并把配置的结果告诉springMVC本身的呢?
这边涉及到两个比较重要的部分,DelegatingWebMvcConfiguration类和EnableWebMvc注解。我们先从简单的EnableWebMvc注解开始。
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Documented
@Import(DelegatingWebMvcConfiguration.class)
public @interface EnableWebMvc {
}
我们可以看到,EnableWebMvc注解最主要的作用就是导入了DelegatingWebMvcConfiguration这个类,所以当我们开启EnableWebMvc注解时,实际上就是导入了DelegatingWebMvcConfiguration这个类,我们再来看看这个类:
@Configuration
public class DelegatingWebMvcConfiguration extends WebMvcConfigurationSupport {
private final WebMvcConfigurerComposite configurers = new WebMvcConfigurerComposite();
// 注入configure集合类
@Autowired(required = false)
public void setConfigurers(List<WebMvcConfigurer> configurers) {
if (!CollectionUtils.isEmpty(configurers)) {
// WebMvcConfigurerComposite类的方法
this.configurers.addWebMvcConfigurers(configurers);
}
}
@Override
protected void configurePathMatch(PathMatchConfigurer configurer) {
this.configurers.configurePathMatch(configurer);
}
@Override
protected void configureContentNegotiation(ContentNegotiationConfigurer configurer) {
this.configurers.configureContentNegotiation(configurer);
}
@Override
protected void configureAsyncSupport(AsyncSupportConfigurer configurer) {
this.configurers.configureAsyncSupport(configurer);
}
// 等等一系列方法。详情可以参考WebMvcConfigurationSupport类
// 它是springMVC实现Java配置的核心类
// 定义了一系列默认的和待提供的配置方法
// 并将这些配置告诉springMVC本身,这里不展开说明。
// ………………
}
从DelegatingWebMvcConfiguration类中我们可以看到,它通过Autowired注解,自动的导入WebMvcConfigurer类的集合。这里实际上就完成了对WebMvcConfigurer对象的探测。
WebMvcConfigurer是一个接口,springMVC的Java配置类大都源自于它,例如WebMvcConfigurerAdapter。所以我们的配置类继承了WebMvcConfigurerAdapter类,并添加Configuration注解后,它就能被DelegatingWebMvcConfiguration类探测并使用。
并且,我们还可以看到这个类维护了一个私有的WebMvcConfigurerComposite对象,它与WebMvcConfigurer息息相关,可以说它和WebMvcConfigurer一起,通过组合模式,实现了对不同配置对象的管理。
WebMvcConfigurerComposite
class WebMvcConfigurerComposite implements WebMvcConfigurer {
private final List<WebMvcConfigurer> delegates = new ArrayList<WebMvcConfigurer>();
public void addWebMvcConfigurers(List<WebMvcConfigurer> configurers) {
// 将传入的WebMvcConfigurer集合赋值给delegates
if (!CollectionUtils.isEmpty(configurers)) {
this.delegates.addAll(configurers);
}
}
@Override
public void configurePathMatch(PathMatchConfigurer configurer) {
for (WebMvcConfigurer delegate : this.delegates) {
delegate.configurePathMatch(configurer);
}
}
@Override
public void configureContentNegotiation(ContentNegotiationConfigurer configurer) {
for (WebMvcConfigurer delegate : this.delegates) {
delegate.configureContentNegotiation(configurer);
}
}
// 重写了一系列方法,参考WebMvcConfigurer接口
}
我们可以看到在WebMvcConfigurerComposite中,每一个方法的参数的类型都是别的类,并且每一个方法都将这些类配置到WebMvcConfigurer类中。
例如addInterceptors方法,它将注册的拦截器加入到WebMvcConfigurer中,最终通过WebMvcConfigurationSupport类提供给springMVC。
通过了组合模式的形式,springMVC将不同的配置(配置同时也是类本身)整合在了同一个整体类中(也就是WebMvcConfigurer)。
总而言之,汇成一句话:springMVC通过组合模式,使得用户或者说框架本身在进行配置时,就通过操作WebMvcConfigurer类及其衍生类这个整体就行了。
总结
组合模式理解起来非常的简单,本章的目的也不仅仅是它本身,也是对springMVC如何实现Java配置进行一个总体的认识,当然许多细节(例如最重要的WebMvcConfigurationSupport)还需要深入的研究。
可以说springMVC把组合模式用在实现Java配置上是很明智和合理的,因为框架的总体配置与相关子配置本来就是整体与部分的关系。
我们在日常的开发中,如果也找到了这些整体-部分的对应关系,那么使用该设计模式可以很好的简化代码量和解耦合。
赶紧在开发中多多考虑可以重构或合理使用设计模式的地方吧。