SpringBoot源码学习系列之SpringMVC自动配置
目录
按照官方文档的说法,SpringBoot官方的说法,Springboot的SpringMVC自动配置,主要提供了如下自动配置:WebMvcAutoConfiguration.java这个类很关键,这个就是SpringBoot Springmvc自动配置的一个很关键的配置类
@Configuration(proxyBeanMethods = false)//指定WebMvcAutoConfiguration不代理方法 @ConditionalOnWebApplication(type = Type.SERVLET)//在web环境(selvlet)才会起效 @ConditionalOnClass({ Servlet.class, DispatcherServlet.class, WebMvcConfigurer.class })//系统有有Servlet,DispatcherServlet(Spring核心的分发器),WebMvcConfigurer的情况,这个自动配置类才起效 @ConditionalOnMissingBean(WebMvcConfigurationSupport.class)//系统没有WebMvcConfigurationSupport这个类的情况,自动配置起效 @AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE + 10) @AutoConfigureAfter({ DispatcherServletAutoConfiguration.class, TaskExecutionAutoConfiguration.class, ValidationAutoConfiguration.class }) public class WebMvcAutoConfiguration { .... }
翻下源码,可以看到WebMvcAutoConfiguration自动配置类里还有一个WebMvcConfigurer类型的配置类,2.2.1版本是implements WebMvcConfigurer接口,1.+版本是extends WebMvcConfigurerAdapter
@Configuration(proxyBeanMethods = false)//定义为配置类 @Import(EnableWebMvcConfiguration.class)//spring底层注解,将EnableWebMvcConfiguration加到容器 @EnableConfigurationProperties({ WebMvcProperties.class, ResourceProperties.class })//使WebMvcProperties、ResourceProperties配置类生效 @Order(0) public static class WebMvcAutoConfigurationAdapter implements WebMvcConfigurer { .... }
1、ContentNegotiatingViewResolver
如图,是视图解析器的自动配置,这个类起效的情况是系统没有ContentNegotiatingViewResolver类的情况,就调用改方法自动创建ContentNegotiatingViewResolver类
关键的是ContentNegotiatingViewResolver类,翻下ContentNegotiatingViewResolver类,找到如下重要的初始化方法@Override protected void initServletContext(ServletContext servletContext) { //调用Spring的BeanFactoryUtils扫描容器里的所有视图解析器ViewResolver类 Collection<ViewResolver> matchingBeans = BeanFactoryUtils.beansOfTypeIncludingAncestors(obtainApplicationContext(), ViewResolver.class).values(); if (this.viewResolvers == null) { this.viewResolvers = new ArrayList<>(matchingBeans.size()); //遍历候选的viewResolvers,封装到this.viewResolvers列表 for (ViewResolver viewResolver : matchingBeans) { if (this != viewResolver) { this.viewResolvers.add(viewResolver); } } } else { for (int i = 0; i < this.viewResolvers.size(); i++) { ViewResolver vr = this.viewResolvers.get(i); if (matchingBeans.contains(vr)) { continue; } String name = vr.getClass().getName() + i; obtainApplicationContext().getAutowireCapableBeanFactory().initializeBean(vr, name); } } AnnotationAwareOrderComparator.sort(this.viewResolvers); this.cnmFactoryBean.setServletContext(servletContext); }
所以ContentNegotiatingViewResolver类的作用就是组合所有的视图解析器,自动配置了ViewResolver(视图解析器作用,根据方法返回值得到视图对象view)
往下翻代码,可以看到resolveViewName方法,里面代码是从this.viewResolvers获取候选的视图解析器,遍历容器里所有视图,然后通过如图所标记的获取候选视图的方法,获取候选的视图列表,再通过getBestView获取最合适的视图
遍历所有的视图解析器对象,从视图解析器里获取候选的视图,封装成list保存
ok,跟了源码就是只要将视图解析器丢到Spring容器里,就可以加载到写个简单的视图解析类
DispatcherServlet是Spring核心分发器,找到doDispatch方法,debug,可以看到加的视图解析器加载到了2、静态资源