原先我们使用Spring MVC开发WEB应用时,会在web.xml中配置一个servlet:DispatcherServlet
Spring Boot一般使用starter来整合第三方框架与扩展功能,在Spring Boot 中使用Spring mvc我们仅需要引入spring-boot-starter-web
其套路是:
定义一个XXXXAutoConfiguration的类。其中XXXX一般可以写成所需集成的功能或框架。其上可定义@Conditional相关注解,指定何时可初始化该功能。
在该类上@Import一个ImportBeanDefinitionRegistrar接口的实现类来注入指定的Bean。
添加自定义的BeanPostProcessor来实现ImportBeanDefinitionRegistrar接口,以便在Bean初始化之前或之后完成配置功能或者初始化某些依赖功能。
在META-INF/spring.factories中定义org.springframework.boot.autoconfigure.EnableAutoConfiguration=<XXXXAutoConfiguration>的完整类名,包括所在包名。Spring Boot在初始化时,会自动扫描spring.factories文件中的相关类,然后初始化并注入到IoC容器中。
spring-boot 默认会自动配置mvc,所以我们通过查看spring-boot-autoconfig包下的spring.factories文件中EnableAutoConfiguration部分时,可以找到一个DispatcherServletAutoConfiguration
这其中存在两个配置类
-
DispatcherServletConfiguration
目的是为了生成DispatcherServlet实例
-
DispatcherServletRegistrationConfiguration
目的是为了将DispatcherServlet实例注入到Servlet容器中
(Servlet3.0规范下是可以通过编程或注解方式配置servlet的无需web.xml)
那么,DispatcherServlet是如何通过编程方式配置到Servlet容器中的呢?
我们继续看代码
org.springframework.boot.autoconfigure.web.servlet.DispatcherServletAutoConfiguration.DispatcherServletRegistrationConfiguration#dispatcherServletRegistration
我们看到实际使用了DispatcherServletRegistrationBean,此时我们看看DispatcherServletRegistrationBean类的关系图
我们看到它实现了接口ServletContextInitializer,那么是谁调用了这个接口中的onStartup方法呢?
(目前还没有找到官方文档中对此的说明,有用参考文档Spring Boot 2.1.8的29.4.2 Servlet Context Initialization)
但是我们可以猜测和通过反向搜索,发现它是在嵌入式容器的启动器中调用的,比如 TomcatStarter
TomcatStarter 又是被谁调用的呢?待继续分析