SpringBootWeb源码解析SpringMVC自动配置

SpringMVC自动配置在 Spring Boot 中引入了 spring-boot-starter-web 依赖 , 并完成了 DispatcherServlet 的自动配置之后 , 便会通过 WebMvcAutoConfiguration 进行 Spring MVC 的自动配置 。
与 DispatcherServletAutoConfiguration 一样 , 首先会在 spring-boot-autoconfigure 包中的ME TA-INF/spring.factories 配置文件中配置注册类 WebMvcAutoConfiguration,源代码如下 。
#自动配置
org. springframework . boot . autoconfigure . EnableAutoConfiguration=\
org. springframework . boot . autoconfigure . web. servlet .WebMvcAutoConfiguratio
n,\
我们直接进入源代码 , 先看 WebMvcAutoConfiguration 的注解部分 。
@Configuration( proxyBeanMethods = false)
@Condit ionalOnWebApplication(type = Type . SERVLET)
@ConditionalOnClass({ Servlet. class, DispatcherServlet.class, WebMvcConfigu
rer.class })
@ConditionalOnMissingBean(WebMvcConfigurationSupport. class)
@AutoConfigureOrder (Ordered . HIGHEST_ PRECEDENCE + 10)
@AutoConfigureAfter({ DispatcherServletAutoConfiguration. class,
TaskExecutionAutoConfiguration . class, Validat ionAutoCo
nfiguration.class })
public class WebMvcAutoConfiguration {
。。。
}
WebMvcAutoConfiguration 类的实例化需要满足很多条件 , 其中就包含必须先完成上节讲到的自动配置 DispatcherServletAutoConfiguration 的初始化 。
Spring MVC 在自动配置中的代码较多 , 官方文档中重点提到了以下功能的实现 。 定义 ContentNegotiatingViewResolver 和 BeanName ViewResolver 的 Bean 。
.对静态资源的支持 , 包括对 WebJars 的支持 。
.自动注册 Converter、 GenericConverter、 Formatter 的 Bean 。
.对 HttpMessageConverters 的支持 。
.自动注册 MessageCodeResolver.
.对静态 index.html 的支持 。
:使用 ConfigurableWebBindingInitializer 的 Bean 。
当然 , 在自动配置类中不只包括了以上的功能实现 , 还包括其他功能 , 限于篇幅 , 这里就不一一-列举 了 。 下面会挑选几个有代表性的功能进行源代码及实例化过程的分析 。
ViewResolver 解析
这里以 ContentNegotiatingViewResolver 和 BeanNameViewResolver 的 bean 的实例化为例进行相应解析 。
ContentNegotiatingViewResolver 实例化相关源代码如下 。
@Bean
@ConditionalOnBean(ViewResolver . class)
@ConditionalOnMissingBean(name = "viewResolver" ,
value = http://kandian.youth.cn/index/ContentNegotiatingViewResolver . class)
public ContentNegot iatingViewResolver viewResolver(BeanFactory beanF actory)
ContentNegotiatingViewResolver resolver = new ContentNegotiatingViewResolver();
resolver . setContentNegotiationManager(
beanF actory. getBean(ContentNegot iationManager . class));
resolver. setOrder (Ordered . HIGHEST_ PRECEDENCE);
return resolver;
}
ContentNegotiatingViewResolver 实例化比较简单 , 创建对象 , 设置请求资源类型管理器为ContentNegotiationManager, 并 设 置 优 先 级。需 要 注 意 的 是,要 让ContentNegotiatingViewResolver 正 常 工 作,需要设置更高的优先级 ( 默认为Ordered.HIGHEST_ PRECEDENCE) 。
ContentNegotiatingViewResolver 类实现了 ViewResolver,但它并不直接解析视图 , 而是委托给其他解析器来完成 。 默认情况 , 它是从 Spring 上下文查找视图解析器 , 并调用这些解析 器。也 可 以 在 初 始 化 该 类 时 通 过 setViewResolvers 方 法 设 置 解 析 器 属 性(viewResolvers)。 在此 , 默认的实例化操作中并没有对 SetViewResolvers 方法进行设置 。
BeanNameViewResolver 实例化相关源码如下 。
@Bean
@ConditionalOnBean(View. class)
@Conditiona lOnMissingBeanpublic BeanNameViewResolver beanNameViewResolver() {
BeanNameViewResolver resolver = new BeanNameViewResolver();
resolver . setOrder(Ordered. LOWEST_ PRECEDENCE- 10);
return resolver;
}
BeanNameViewResolver 主要通过逻辑视图名称匹配定义好的视图 Bean 对象 。 一般情况下 , 对应的 Bean 对象需要注册到 Spring 的上下文中,BeanNameViewResolver 会返回名称匹配的视图对象 。
BeanNameViewResolver 实例化的前提条件是容器中 View 实现类的 Bean 存在 。
BeanNameViewResolver 的部分源码如下 。
public class BeanNameViewResolver extends WebApplicationObjectSupport imple
ments ViewResolver, Ordered {
//实现 Ordered 接口 , 支持对 ViewResolver 排序 ,值越小优先级越高
private int order = Ordered. LOWEST_ PRECEDENCE;
@Override
@Nullable
public View resolveVi ewName (String viewName, Locale locale) throws Beans -
Exception
//获取上下文
ApplicationContext context = obtainApplicationContext();
//查找上下文中是否有"viewName”的 Bean 定义
if (!context . containsBean(viewName)) {
return null;
}
//判断"viewName”的 bean 对象是否是 View 类型