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