@EnableWebMvc 为容器注入了DelegatingWebMvcConfiguration类
此类的作用主要是开启定制mvc的功能,实质就是整合了applicationConfig实现了WebMvcConfigurer后对某些功能如视图解析器的自定义实现
configuers会保存ApplicationConfig实例,原因:
spring源码解析 --AutowiredAnnotationBeanPostProcessor_asLightYouAre的博客-CSDN博客
保存的形式
其父类WebMvcConfigurationSupport中定义了大量的@Bean其中也包括视图解析器的集合
@Bean
public ViewResolver mvcViewResolver(
@Qualifier("mvcContentNegotiationManager") ContentNegotiationManager contentNegotiationManager) {
//创建一个视图解析器的注册器
ViewResolverRegistry registry =
new ViewResolverRegistry(contentNegotiationManager, this.applicationContext);
//代码段外分析,先看代码段外的分析
configureViewResolvers(registry);
if (registry.getViewResolvers().isEmpty() && this.applicationContext != null) {
String[] names = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
this.applicationContext, ViewResolver.class, true, false);
if (names.length == 1) {
registry.getViewResolvers().add(new InternalResourceViewResolver());
}
}
//创建视图解析器集合
ViewResolverComposite composite = new ViewResolverComposite();
//视图解析器优先级设置
composite.setOrder(registry.getOrder());
//向集合中注入视图解析器
composite.setViewResolvers(registry.getViewResolvers());
if (this.applicationContext != null) {
//将容器注入视图解析器,后面有用
composite.setApplicationContext(this.applicationContext);
}
if (this.servletContext != null) {
composite.setServletContext(this.servletContext);
}
return composite;
}
首先遍历delegates,由于只有一个applicationConfig实现了WebMvcConfigure,
调用delegate#configureViewResolvers,这里就是我们的applicationConfig所重写的自定义视图解析器的configureViewResolvers方法
其中就可以向视图解析器的注册器中注册视图解析器
调用结束回到之前的代码段继续查看
将容器注入视图解析器
由于注册的视图解析器InternalResourceViewResolver有实现ApplicationContextAware
所以可以将容器注入其中
至此ViewResolver实例便创建成功,但是是怎么添加进DispatcherServlet的
容器创建完成后会发布事件
DispatcherServlet的父类FrameworkServlet内部类ContextRefreshListener(已经注入到了容器的监听器集合里)可以监听到这一事件,Source就是容器对象,就可以进行DispatcherServlet的初始化
方法栈调用情况
DispatcherServlet#initStrategies就会通过容器对象进行包括视图解析器注册等一系列初始化
所以若是静态资源没有交给 DispatcherServlet而是分发给了tomcat的默认静态资源处理器,那么视图解析器就会失效。
最后对于@Bean为什么会在生成时不是通过构造器而是调用 @Bean标记的方法是因为
在最开始对配置类进行扫描时注册bean信息时,会对@Bean标记的方法在bean信息里注入
beanfactorymethod,最后在doCreateBean实例化时会通过判断,通过了就会采用这种策略