SpringMVC源码-创建ContentNegotiationManagerFactoryBean
一、ContentNegotiationManagerFactoryBean的BeanDifinition及实现的接口
上图的属性说的是ContentNegotiationManagerFactoryBean对应的BeanDifinition中设置的属性,需要被注入bean中。右边表示实现的接口。
ContentNegotiationManagerFactoryBean实现了FactoryBean
ContentNegotiationManager用于解析请求中的MediaType,及将MediaType解析成文件扩展名。
二、实例化ContentNegotiationManagerFactoryBean
在ContentNegotiationManagerFactoryBean.doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)中:
BeanWrapper instanceWrapper = null;
if (mbd.isSingleton()) {
instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
}
if (instanceWrapper == null) {
instanceWrapper = createBeanInstance(beanName, mbd, args);
}
createBeanInstance调用了ContentNegotiationManagerFactoryBean的默认构造方法实例化对象。
populateBean(beanName, mbd, instanceWrapper);
exposedObject = initializeBean(beanName, exposedObject, mbd);
populateBean填充mediaTypes属性。initializeBean调用bean的init方法,即实现了InitializingBean接口的afterPropertiesSet方法。
ContentNegotiationManagerFactoryBean.afterPropertiesSet()
public void afterPropertiesSet() {
build();
}
ContentNegotiationManagerFactoryBean.build()
public ContentNegotiationManager build() {
List<ContentNegotiationStrategy> strategies = new ArrayList<>();
if (this.strategies != null) {
strategies.addAll(this.strategies);
}
else {
if (this.favorPathExtension) {
PathExtensionContentNegotiationStrategy strategy;
if (this.servletContext != null && !useRegisteredExtensionsOnly()) {
strategy = new ServletPathExtensionContentNegotiationStrategy(this.servletContext, this.mediaTypes);
}
else {
strategy = new PathExtensionContentNegotiationStrategy(this.mediaTypes);
}
strategy.setIgnoreUnknownExtensions(this.ignoreUnknownPathExtensions);
if (this.useRegisteredExtensionsOnly != null) {
strategy.setUseRegisteredExtensionsOnly(this.useRegisteredExtensionsOnly);
}
strategies.add(strategy);
}
if (this.favorParameter) {
ParameterContentNegotiationStrategy strategy = new ParameterContentNegotiationStrategy(this.mediaTypes);
strategy.setParameterName(this.parameterName);
if (this.useRegisteredExtensionsOnly != null) {
strategy.setUseRegisteredExtensionsOnly(this.useRegisteredExtensionsOnly);
}
else {
strategy.setUseRegisteredExtensionsOnly(true); // backwards compatibility
}
strategies.add(strategy);
}
if (!this.ignoreAcceptHeader) {
strategies.add(new HeaderContentNegotiationStrategy());
}
if (this.defaultNegotiationStrategy != null) {
strategies.add(this.defaultNegotiationStrategy);
}
}
this.contentNegotiationManager = new ContentNegotiationManager(strategies);
// Ensure media type mappings are available via ContentNegotiationManager#getMediaTypeMappings()
// independent of path extension or parameter strategies.
if (!CollectionUtils.isEmpty(this.mediaTypes) && !this.favorPathExtension && !this.favorParameter) {
this.contentNegotiationManager.addFileExtensionResolvers(
new MappingMediaTypeFileExtensionResolver(this.mediaTypes));
}
return this.contentNegotiationManager;
}
favorPathExtension表示将mediaTypes解析成文件扩展名。默认为false。ServletPathExtensionContentNegotiationStrategy使用ServletContext#getMimeType(String)解析成文件扩展名。PathExtensionContentNegotiationStrategy--解析请求用于查找媒体类型的键的路径。
favorParameter表示是否将查询参数解析成content type。默认为false。ParameterContentNegotiationStrategy将查询参数解析成content type的策略。
ignoreAcceptHeader表示是否忽略Accept请求头。HeaderContentNegotiationStrategy检查Accept请求头。
MappingMediaTypeFileExtensionResolver是MediaType到文件扩展名的解析器。