SpringBoot源码解析-⾃动配置SpringMVC
在上⼀⼩节,我们介绍了SpringBoot是如何启动⼀个内置tomcat的。
我们知道我们在SpringBoot项⽬⾥⾯是可以直接使⽤诸如@RequestMapping 这类的SpringMVC的注解,那么同学们会不会奇怪,这是为什么?
我明明没有配置SpringMVC为什么就可以使⽤呢?
其实仅仅引⼊starter是不够的,回忆⼀下,在⼀个普通的WEB项⽬中如何去使⽤SpringMVC,我们⾸先就是要在l中配置如下配置
<servlet>
<description>spring mvc servlet</description>
<servlet-name>springMvc</servlet-name>
<servletclass>
org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>springMvc</servlet-name>
<url-pattern>*.do</url-pattern>
</servlet-mapping>
但是在SpringBoot中,我们没有了l⽂件,我们如何去配置⼀个Dispatcherservlet 呢?
其实Servlet3.0规范中规定,要添加⼀个Servlet,除了采⽤xml配置的⽅式,还有⼀种通过代码的⽅式,伪代码如下servletContext.addServlet(name, this.servlet);
spring mvc和boot区别
那么也就是说,如果我们能动态往web容器中添加⼀个我们构造好的DispatcherServlet 对象,是不是就实现⾃动装配SpringMVC了⼀、⾃动配置DispatcherServlet和DispatcherServletRegistry
springboot的⾃动配置基于SPI机制,实现⾃动配置的核⼼要点就是添加⼀个⾃动配置的类,SpringBo
ot MVC的⾃动配置⾃然也是相同原理。
所以,先到springmvc对应的⾃动配置类。
1.1 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中。
1.2 配置DispatcherServletConfiguration
我们先看看DispatcherServletConfiguration这个配置类
@Conditional指明了⼀个前置条件判断,由DefaultDispatcherServletCondition实现。主要是判断了是否已经存在
DispatcherServlet,如果没有才会触发解析。
@ConditionalOnClass指明了当ServletRegistration这个类存在的时候才会触发解析,⽣成的DispatcherServlet才能注册到ServletContext中。
@EnableConfigrationProperties将会从application.properties这样的配置⽂件中读取spring.http和spring.mvc前缀的属性⽣成配置对象HttpProperties和WebMvcProperties。
再看DispatcherServletConfiguration这个内部类的内部代码
这个两个⽅法我们⽐较熟悉了,就是⽣成了Bean。
dispatcherServlet⽅法将⽣成⼀个DispatcherServlet的Bean对象。⽐较简单,就是获取⼀个实例,然后添加⼀些属性设置。
multipartResolver⽅法主要是把你配置的MultipartResolver的Bean给重命名⼀下,防⽌你不是⽤multipartResolver这个名字作为Bean的名字。
1.3 配置DispatcherServletRegistrationConfiguration
再看注册类的Bean配置
@Conditional有⼀个前置判断,DispatcherServletRegistrationCondition主要判断了该注册类的Bean是否存在。
@ConditionOnClass也判断了ServletRegistration是否存在
@EnableConfigurationProperties⽣成了WebMvcProperties的属性对象
@Import导⼊了DispatcherServletConfiguration,也就是我们上⾯的配置对象。
再看DispatcherServletRegistrationConfiguration的内部实现
内部只有⼀个⽅法,⽣成了DispatcherServletRegistrationBean。
核⼼逻辑就是实例化了⼀个Bean,设置了⼀些参数,如dispatcherServlet、loadOnStartup等。
1.3 总结
springboot mvc的⾃动配置类是DispatcherServletAutoConfigration,主要做了两件事:
1)配置DispatcherServlet
2)配置DispatcherServlet的注册Bean(DispatcherServletRegistrationBean)
⼆、注册DispatcherServlet到ServletContext
在上⼀⼩节的源码翻阅中,我们看到了DispatcherServlet和DispatcherServletRegistrationBean这两个Bean的⾃动配置。
DispatcherServlet我们很熟悉,DispatcherServletRegistrationBean负责将DispatcherServlet注册到ServletContext当中2.1 DispatcherServletRegistrationBean的类图
既然该类的职责是负责注册DispatcherServlet,那么我们得知道什么时候触发注册操作。
为此,我们先看看DispatcherServletRegistrationBean这个类的类图
2.2 注册DispatcherServlet流程
2.2.1 ServletContextInitializer
我们看到,最上⾯是⼀个ServletContextInitializer接⼝。我们可以知道,实现该接⼝意味着是⽤来初始化ServletContext的。我们看看该接⼝
2.2.2 RegistrationBean
看看RegistrationBean是怎么实现onStartup⽅法的
调⽤了内部register⽅法,跟进它
这是⼀个抽象⽅法
2.2.3 DynamicRegistrationBean
再看DynamicRegistrationBean是怎么实现register⽅法的