Spring boot源码一:集成Web MVC

在spring中的spring-boot-autoconfigure包下面有个spring.factories文件,包含了所有Spring boot默认的配置,其中有一个是WebMvcAutoConfiguration,这里会配置所有MVC须要的相关配置项(HandlerMapping&ViewResolver&MessageConverter等)。

我们看下这个类上的注解可以发现其启用须要一些条件:

Spring boot源码一:集成Web MVC

首先工程下必须有Servlet相关的类,所以其底层也是MVC那套DispatcherServlet逻辑。

然后不能有WebMvcConfigurationSupport类,这是一个关键,所以说假如使用了Spring Boot的话,我们在工程中就不能使用WebMvcConfigurationSupport这个类了,同时也不能使用@EnableWebMvc这个注解,因为这个注解也会导入一个WebMvcConfigurationSupport的子类,否则Spring Boot关于Web MVC的自动配置就不生效了!

另外WebMvcAutoConfiguration的执行时机是在DispatcherServletAutoConfiguration之后的,这个也很好理解,我们须要先把DispatcherServlet初始化好之后,再去搞各种MVC的相关配置。

DispatcherServletAutoConfiguration中,我们不去研究太深,主要看三个地方。

1.通过@EnableConfigurationProperties注解启用了ServerProperties这个bean。

Spring boot源码一:集成Web MVC

ServerProperties会通过@ConfigurationProperties注解,加载属性文件中以server开头的属性,我们常用server.port就是被ServerProperties加载了的。

Spring boot源码一:集成Web MVC

这两个注解都是Spring Boot中的应用,这里也不展开来讲了。

2.将DispatcherServlet实例化出来

Spring boot源码一:集成Web MVC

这里同理用到了WebMvcProperties这个属性类,会加载属性文件中以spring.mvc开头的属性。

3.将DispatcherServlet赋给一个DispatcherServletRegistrationBean

Spring boot源码一:集成Web MVC

这里为什么要这么做,我们可以看一下DispatcherServletRegistrationBean的的类继承关系图:

Spring boot源码一:集成Web MVC

圈出来的这块是重点,这里就又要讲到Spring实现Servlet3.0的规范了,之前讲Spring MVC源码中讲过。

这里我们找一个TomcatStarter类(注意这里只是说tomcat的情况下,当web容器不同时,对应的类也是不同的),可以看到其继承了ServletContainerInitializer,所以当web容器启动时,会调用这个类的onStartup方法。

Spring boot源码一:集成Web MVC

这里的ServletContextInitializer是不是很熟悉,没错,之前关系图中清晰的告诉我们,其是DispatcherServletRegistrationBean的父类。

所以我们可以理解为,当通过DispatcherServletAutoConfiguration配置类将DispatcherServletRegistrationBean对象注册为bean之后,这个bean会在TomcatStarter的onStartup方法中执行其父类ServletContextInitializer的onStartup方法!而目前这个bean中已经有DispatcherServlet的引用了。

onStartup方法的执行过程中,会调用其一级父类ServletRegistrationBean的addRegistration方法:

Spring boot源码一:集成Web MVC

这里就很明确了,将DispatcherServlet添加到了Servlet的上下文中了。

Spring Boot中内置的ServletContextInitializer的子类还有很多,如下图,可以看到同样的方式我们可以配置过滤器;监听器交给Servlet上下文:

Spring boot源码一:集成Web MVC

总结:

虽然最终都是将DispatcherServlet添加到Servlet的上下文中,但是和Spring MVC的流程还是有些区别的,这里再来归纳一波:

Spring MVC

通过实现Servlet3.0的规范,须要手动实现WebApplicationInitializer接口,将DispatcherServlet添加给Servlet的上下文。

Spring Boot

同样实现Servlet3.0的规范,通过DispatcherServletAutoConfiguration将DispatcherServlet和DispatcherServletRegistrationBean对象实例化为bean,最后通过调用TomcatStarter#onStartup方法将DispatcherServlet添加给Servlet的上下文。这些都是Spring Boot自动帮我们实现的,我们须要做的仅仅是配置一些属性,相比MVC就方便多了。