SpringMVC源码-创建ContentNegotiationManagerFactoryBean

一、ContentNegotiationManagerFactoryBean的BeanDifinition及实现的接口

上图的属性说的是ContentNegotiationManagerFactoryBean对应的BeanDifinition中设置的属性,需要被注入bean中。右边表示实现的接口。

ContentNegotiationManagerFactoryBean实现了FactoryBean接口用于创建ContentNegotiationManager类型的bean实例。同时配置ContentNegotiationStrategy实例。

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到文件扩展名的解析器。

posted @ 2022-11-01 20:17  shigp1  阅读(160)  评论(0编辑  收藏  举报