浅谈springMVC中的设计模式(5)——组合模式

相信大家在使用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配置上是很明智和合理的,因为框架的总体配置与相关子配置本来就是整体与部分的关系。
我们在日常的开发中,如果也找到了这些整体-部分的对应关系,那么使用该设计模式可以很好的简化代码量和解耦合。
赶紧在开发中多多考虑可以重构或合理使用设计模式的地方吧。

猜你喜欢

转载自blog.csdn.net/ljw761123096/article/details/79834854