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


所有文章

https://www.cnblogs.com/lay2017/p/11775787.html

 

正文

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

本文開始,我們將討論Springboot下Servlet的web實現。所以,先找到對應的自動配置類。

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

 

DispatcherServletAutoConfiguration自動配置類

我們打開該類

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

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

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

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

4、@AutoConfigureAfter指明在ServletWebServerFactoryAutoConfiguration這個類之后再解析,設定了一個順序。

總的來說,這些注解表明了該自動配置類的會解析的前置條件需要滿足。

 

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

1、DispatcherServletConfiguration

2、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

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM