1. 程式人生 > >淺談springMVC中的設計模式(5)——組合模式

淺談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配置上是很明智和合理的,因為框架的總體配置與相關子配置本來就是整體與部分的關係。
我們在日常的開發中,如果也找到了這些整體-部分的對應關係,那麼使用該設計模式可以很好的簡化程式碼量和解耦合。
趕緊在開發中多多考慮可以重構或合理使用設計模式的地方吧。