springboot mvc自動配置(一)自動配置DispatcherServlet和DispatcherServletRegistry

全部文章

http://www.javashuo.com/article/p-mbkpimnl-cg.htmlhtml

 

正文

springboot的自動配置基於SPI機制,實現自動配置的核心要點就是添加一個自動配置的類,SpringBoot MVC的自動配置天然也是相同原理。web

本文開始,咱們將討論Springboot下Servlet的web實現。因此,先找到對應的自動配置類。spring

org.springframework.boot.autoconfigure.web.servlet.DispatcherServletAutoConfiguration

 

DispatcherServletAutoConfiguration自動配置類

咱們打開該類tomcat

@AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE)
@Configuration(proxyBeanMethods = false)
@ConditionalOnWebApplication(type = Type.SERVLET)
@ConditionalOnClass(DispatcherServlet.class)
@AutoConfigureAfter(ServletWebServerFactoryAutoConfiguration.class)
public class DispatcherServletAutoConfiguration {
    //...
}

一、首先注意到,@Configuration表名這是一個配置類,將會被spring給解析。springboot

二、@ConditionalOnWebApplication意味着當時一個web項目,且是Servlet項目的時候纔會被解析。mvc

三、@ConditionalOnClass指明DispatcherServlet這個核心類必須存在才解析該類。app

四、@AutoConfigureAfter指明在ServletWebServerFactoryAutoConfiguration這個類以後再解析,設定了一個順序。ide

總的來講,這些註解代表了該自動配置類的會解析的前置條件須要知足。spa

 

其次,DispatcherServletAutoConfiguration類主要包含了兩個內部類,分別是code

一、DispatcherServletConfiguration

二、DispatcherServletRegistrationConfiguration

顧名思義,前者是配置DispatcherServlet,後者是配置DispatcherServlet的註冊類。什麼是註冊類?咱們知道Servlet實例是要被添加(註冊)到如tomcat這樣的ServletContext裏的,這樣纔可以提供請求服務。因此,DispatcherServletRegistrationConfiguration將生成一個Bean,負責將DispatcherServlet給註冊到ServletContext中。

 

配置DispatcherServletConfiguration

咱們先看看DispatcherServletConfiguration這個配置類

@Configuration(proxyBeanMethods = false)
@Conditional(DefaultDispatcherServletCondition.class)
@ConditionalOnClass(ServletRegistration.class)
@EnableConfigurationProperties({ HttpProperties.class, WebMvcProperties.class })
protected static class DispatcherServletConfiguration {

    //...
}

@Conditional指明瞭一個前置條件判斷,由DefaultDispatcherServletCondition實現。主要是判斷了是否已經存在DispatcherServlet,若是沒有才會觸發解析。

@ConditionalOnClass指明瞭當ServletRegistration這個類存在的時候纔會觸發解析,生成的DispatcherServlet才能註冊到ServletContext中。

最後,@EnableConfigrationProperties將會從application.properties這樣的配置文件中讀取spring.http和spring.mvc前綴的屬性生成配置對象HttpProperties和WebMvcProperties。

 

再看DispatcherServletConfiguration這個內部類的內部代碼

@Bean(name = DEFAULT_DISPATCHER_SERVLET_BEAN_NAME)
public DispatcherServlet dispatcherServlet(HttpProperties httpProperties, WebMvcProperties webMvcProperties) {
    DispatcherServlet dispatcherServlet = new DispatcherServlet();
    dispatcherServlet.setDispatchOptionsRequest(webMvcProperties.isDispatchOptionsRequest());
    dispatcherServlet.setDispatchTraceRequest(webMvcProperties.isDispatchTraceRequest());
    dispatcherServlet.setThrowExceptionIfNoHandlerFound(webMvcProperties.isThrowExceptionIfNoHandlerFound());
    dispatcherServlet.setPublishEvents(webMvcProperties.isPublishRequestHandledEvents());
    dispatcherServlet.setEnableLoggingRequestDetails(httpProperties.isLogRequestDetails());
    return dispatcherServlet;
}

@Bean
@ConditionalOnBean(MultipartResolver.class)
@ConditionalOnMissingBean(name = DispatcherServlet.MULTIPART_RESOLVER_BEAN_NAME)
public MultipartResolver multipartResolver(MultipartResolver resolver) {
    // Detect if the user has created a MultipartResolver but named it incorrectly
    return resolver;
}

這個兩個方法咱們比較熟悉了,就是生成了Bean。

dispatcherServlet方法將生成一個DispatcherServlet的Bean對象。比較簡單,就是獲取一個實例,而後添加一些屬性設置。

multipartResolver方法主要是把你配置的MultipartResolver的Bean給重命名一下,防止你不是用multipartResolver這個名字做爲Bean的名字。

 

配置DispatcherServletRegistrationConfiguration

再看註冊類的Bean配置

@Configuration(proxyBeanMethods = false)
@Conditional(DispatcherServletRegistrationCondition.class)
@ConditionalOnClass(ServletRegistration.class)
@EnableConfigurationProperties(WebMvcProperties.class)
@Import(DispatcherServletConfiguration.class)
protected static class DispatcherServletRegistrationConfiguration {
    //...
}

一樣的,@Conditional有一個前置判斷,DispatcherServletRegistrationCondition主要判斷了該註冊類的Bean是否存在。

@ConditionOnClass也判斷了ServletRegistration是否存在

@EnableConfigurationProperties生成了WebMvcProperties的屬性對象

@Import導入了DispatcherServletConfiguration,也就是咱們上面的配置對象。

 

再看DispatcherServletRegistrationConfiguration的內部實現

@Bean(name = DEFAULT_DISPATCHER_SERVLET_REGISTRATION_BEAN_NAME)
@ConditionalOnBean(value = DispatcherServlet.class, name = DEFAULT_DISPATCHER_SERVLET_BEAN_NAME)
public DispatcherServletRegistrationBean dispatcherServletRegistration(DispatcherServlet dispatcherServlet,
        WebMvcProperties webMvcProperties, ObjectProvider<MultipartConfigElement> multipartConfig) {
    DispatcherServletRegistrationBean registration = new DispatcherServletRegistrationBean(dispatcherServlet,
            webMvcProperties.getServlet().getPath());
    registration.setName(DEFAULT_DISPATCHER_SERVLET_BEAN_NAME);
    registration.setLoadOnStartup(webMvcProperties.getServlet().getLoadOnStartup());
    multipartConfig.ifAvailable(registration::setMultipartConfig);
    return registration;
}

內部只有一個方法,生成了DispatcherServletRegistrationBean。核心邏輯就是實例化了一個Bean,設置了一些參數,如dispatcherServlet、loadOnStartup等。

 

總結

springboot mvc的自動配置類是DispatcherServletAutoConfigration,主要作了兩件事:

1)配置DispatcherServlet

2)配置DispatcherServlet的註冊Bean

相關文章
相關標籤/搜索