Springboot自動裝配之註入DispatcherServlet的實現方法
原理概述
Springboot向外界提供web服務,底層依賴瞭springframework中的web模塊(包含但不限於spring mvc核心類DispatcherServlet)來實現
那麼springboot在什麼時機向容器註入DispatcherServlet這個核心類的呢
註入的流程還是遵循瞭自動裝配流程,在springboot框架裡默認提供瞭該自動裝配的支持
在jar包裡的spring.factories文件裡有個 org.springframework.boot.autoconfigure.web.servlet.DispatcherServletAutoConfiguration配置
@AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE) @Configuration(proxyBeanMethods = false) @ConditionalOnWebApplication(type = Type.SERVLET) @ConditionalOnClass(DispatcherServlet.class) @AutoConfigureAfter(ServletWebServerFactoryAutoConfiguration.class) public class DispatcherServletAutoConfiguration { /* * The bean name for a DispatcherServlet that will be mapped to the root URL "/" */ public static final String DEFAULT_DISPATCHER_SERVLET_BEAN_NAME = "dispatcherServlet"; /* * The bean name for a ServletRegistrationBean for the DispatcherServlet "/" * public static final String DEFAULT_DISPATCHER_SERVLET_REGISTRATION_BEAN_NAME = "dispatcherServletRegistration"; // ... 省略代碼 }
在DispatcherServletAutoConfiguration中有兩個內部類(配置類) DispatcherServletConfiguration、DispatcherServletRegistrationConfiguration和兩個對應的Condition類DefaultDispatcherServletCondition、DispatcherServletRegistrationCondition
DispatcherServletConfiguration
DispatcherServletConfiguration是DispatcherServletAutoConfiguration 的一個內部類,並被 @Configuration標註,會被容器自動掃描到;其有兩個方法: 1、dispatcherServlet;2、multipartResolver
@Configuration(proxyBeanMethods = false) @Conditional(DefaultDispatcherServletCondition.class) @ConditionalOnClass(ServletRegistration.class) @EnableConfigurationProperties({ HttpProperties.class, WebMvcProperties.class }) protected static class DispatcherServletConfiguration { // @A @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; } // @B @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; } }
@A:
- @Configuration(proxyBeanMethods = false):配置類采用Lite模式
- @Conditional(DefaultDispatcherServletCondition.class):根據DefaultDispatcherServletCondition類返回值計算是否要註入,主要邏輯是檢驗Spring容器中是否已經存在一個名字為"dispatcherServlet"的DispatcherServlet
- @ConditionalOnClass(ServletRegistration.class):容器中必須要有ServletRegistration類
- @EnableConfigurationProperties({ HttpProperties.class, WebMvcProperties.class }):加載HttpProperties和WebMvcProperties
@B:註入 MultipartResolver 解析類
DispatcherServletRegistrationConfiguration
該類註入的邏輯與DispatcherServletConfiguration 相同,隻不過在類上註解瞭 @Import(DispatcherServletConfiguration.class)那麼這兩個類定義就有瞭先後順序
@Configuration(proxyBeanMethods = false) @Conditional(DispatcherServletRegistrationCondition.class) @ConditionalOnClass(ServletRegistration.class) @EnableConfigurationProperties(WebMvcProperties.class) @Import(DispatcherServletConfiguration.class) //@A protected static class 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繼承自ServletRegistrationBean,主要為DispatcherServlet提供服務。DispatcherServletRegistrationBean和DispatcherServlet都提供瞭註冊Servlet並公開DispatcherServletPath信息的功能
面試點
spring mvc和spring boot的關系,相信讀瞭上面的文章會說出一兩點;
到此這篇關於Springboot自動裝配之註入DispatcherServlet的文章就介紹到這瞭,更多相關Springboot註入DispatcherServlet內容請搜索WalkonNet以前的文章或繼續瀏覽下面的相關文章希望大傢以後多多支持WalkonNet!
推薦閱讀:
- SpringBoot2入門自動配置原理及源碼分析
- spring boot 加載web容器tomcat流程源碼分析
- 聊聊SpringBoot自動裝配的魔力
- 詳解如何實現SpringBoot的底層註解
- Springboot配置suffix指定mvc視圖的後綴方法