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
咱們打開該類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這個配置類
@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的名字。
再看註冊類的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