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