首页 > 编程语言 >SpringMVC源码-创建FormattingConversionServiceFactoryBean

SpringMVC源码-创建FormattingConversionServiceFactoryBean

时间:2022-11-02 20:57:59浏览次数:91  
标签:converterRegistry SpringMVC addConverter FormattingConversionServiceFactoryBean 

一、FormattingConversionServiceFactoryBean

FormattingConversionServiceFactoryBean实现了FactoryBean接口,可以通过getObject获取ConversionService。FormattingConversionServiceFactoryBean提供了快速访问ConversionService工厂,工厂配置了转换器和格式化程序(用于常见类型,如数字和日期时间)。

二、实例化FormattingConversionServiceFactoryBean
AbstractAutowireCapableBeanFactory.initializeBean执行bean的init方法,实现InitializingBean接口的InitializingBean方法,及执行实现BeanPostProcessor接口的postProcessBeforeInitialization和postProcessAfterInitialization。

FormattingConversionServiceFactoryBean.afterPropertiesSet()

	public void afterPropertiesSet() {
	this.conversionService = new DefaultFormattingConversionService(this.embeddedValueResolver, this.registerDefaultFormatters);
	ConversionServiceFactory.registerConverters(this.converters, this.conversionService);
	registerFormatters(this.conversionService);
}

1、创建DefaultFormattingConversionService
2、调用ConversionServiceFactory.registerConverters注册给定的converters
3、registerFormatters注册Formatter

DefaultFormattingConversionService

public DefaultFormattingConversionService(
		@Nullable StringValueResolver embeddedValueResolver, boolean registerDefaultFormatters) {

	if (embeddedValueResolver != null) {
		setEmbeddedValueResolver(embeddedValueResolver);
	}
	DefaultConversionService.addDefaultConverters(this);
	if (registerDefaultFormatters) {
		addDefaultFormatters(this);
	}
}

1、设置ValueResolver
2、添加默认Converter
3、添加默认Formatter

DefaultConversionService.addDefaultConverters(ConverterRegistry converterRegistry)

	public static void addDefaultConverters(ConverterRegistry converterRegistry) {
	addScalarConverters(converterRegistry);
	addCollectionConverters(converterRegistry);

	converterRegistry.addConverter(new ByteBufferConverter((ConversionService) converterRegistry));
	converterRegistry.addConverter(new StringToTimeZoneConverter());
	converterRegistry.addConverter(new ZoneIdToTimeZoneConverter());
	converterRegistry.addConverter(new ZonedDateTimeToCalendarConverter());

	converterRegistry.addConverter(new ObjectToObjectConverter());
	converterRegistry.addConverter(new IdToEntityConverter((ConversionService) converterRegistry));
	converterRegistry.addConverter(new FallbackObjectToStringConverter());
	converterRegistry.addConverter(new ObjectToOptionalConverter((ConversionService) converterRegistry));
}

1、addScalarConverters添加ConverterFactory及Converter,ConverterFactory<S, R>将对象从S转换为R的子类型。
2、addCollectionConverters添加collection converters
3、添加默认Converter

addScalarConverters(ConverterRegistry converterRegistry)

	private static void addScalarConverters(ConverterRegistry converterRegistry) {
	converterRegistry.addConverterFactory(new NumberToNumberConverterFactory());

	converterRegistry.addConverterFactory(new StringToNumberConverterFactory());
	converterRegistry.addConverter(Number.class, String.class, new ObjectToStringConverter());

	converterRegistry.addConverter(new StringToCharacterConverter());
	converterRegistry.addConverter(Character.class, String.class, new ObjectToStringConverter());

	converterRegistry.addConverter(new NumberToCharacterConverter());
	converterRegistry.addConverterFactory(new CharacterToNumberFactory());

	converterRegistry.addConverter(new StringToBooleanConverter());
	converterRegistry.addConverter(Boolean.class, String.class, new ObjectToStringConverter());

	converterRegistry.addConverterFactory(new StringToEnumConverterFactory());
	converterRegistry.addConverter(new EnumToStringConverter((ConversionService) converterRegistry));

	converterRegistry.addConverterFactory(new IntegerToEnumConverterFactory());
	converterRegistry.addConverter(new EnumToIntegerConverter((ConversionService) converterRegistry));

	converterRegistry.addConverter(new StringToLocaleConverter());
	converterRegistry.addConverter(Locale.class, String.class, new ObjectToStringConverter());

	converterRegistry.addConverter(new StringToCharsetConverter());
	converterRegistry.addConverter(Charset.class, String.class, new ObjectToStringConverter());

	converterRegistry.addConverter(new StringToCurrencyConverter());
	converterRegistry.addConverter(Currency.class, String.class, new ObjectToStringConverter());

	converterRegistry.addConverter(new StringToPropertiesConverter());
	converterRegistry.addConverter(new PropertiesToStringConverter());

	converterRegistry.addConverter(new StringToUUIDConverter());
	converterRegistry.addConverter(UUID.class, String.class, new ObjectToStringConverter());
}

比如StringToNumberConverterFactory将String转换成Number的子类型。EnumToStringConverter将Enum转换成String.

addCollectionConverters(ConverterRegistry converterRegistry)

public static void addCollectionConverters(ConverterRegistry converterRegistry) {
	ConversionService conversionService = (ConversionService) converterRegistry;

	converterRegistry.addConverter(new ArrayToCollectionConverter(conversionService));
	converterRegistry.addConverter(new CollectionToArrayConverter(conversionService));

	converterRegistry.addConverter(new ArrayToArrayConverter(conversionService));
	converterRegistry.addConverter(new CollectionToCollectionConverter(conversionService));
	converterRegistry.addConverter(new MapToMapConverter(conversionService));

	converterRegistry.addConverter(new ArrayToStringConverter(conversionService));
	converterRegistry.addConverter(new StringToArrayConverter(conversionService));

	converterRegistry.addConverter(new ArrayToObjectConverter(conversionService));
	converterRegistry.addConverter(new ObjectToArrayConverter(conversionService));

	converterRegistry.addConverter(new CollectionToStringConverter(conversionService));
	converterRegistry.addConverter(new StringToCollectionConverter(conversionService));

	converterRegistry.addConverter(new CollectionToObjectConverter(conversionService));
	converterRegistry.addConverter(new ObjectToCollectionConverter(conversionService));

	converterRegistry.addConverter(new StreamConverter(conversionService));
}

StringToCollectionConverter将String分割后转换成Collection。

DefaultFormattingConversionService.addDefaultFormatters(FormatterRegistry formatterRegistry)

	public static void addDefaultFormatters(FormatterRegistry formatterRegistry) {
	// Default handling of number values
	formatterRegistry.addFormatterForFieldAnnotation(new NumberFormatAnnotationFormatterFactory());

	// Default handling of monetary values
	if (jsr354Present) {
		formatterRegistry.addFormatter(new CurrencyUnitFormatter());
		formatterRegistry.addFormatter(new MonetaryAmountFormatter());
		formatterRegistry.addFormatterForFieldAnnotation(new Jsr354NumberFormatAnnotationFormatterFactory());
	}

	// Default handling of date-time values

	// just handling JSR-310 specific date and time types
	new DateTimeFormatterRegistrar().registerFormatters(formatterRegistry);

	if (jodaTimePresent) {
		// handles Joda-specific types as well as Date, Calendar, Long
		new org.springframework.format.datetime.joda.JodaTimeFormatterRegistrar().registerFormatters(formatterRegistry);
	}
	else {
		// regular DateFormat-based Date, Calendar, Long converters
		new DateFormatterRegistrar().registerFormatters(formatterRegistry);
	}
}

NumberFormatAnnotationFormatterFactory用于处理@NumberFormat标注的字段。@NumberFormat可参考https://blog.csdn.net/weixin_38192427/article/details/122270716

jsr354Present表示是否要处理MonetaryAmount。MonetaryAmount参考https://www.cnblogs.com/vivotech/p/15686492.html。
CurrencyUnitFormatter用于货币类型与String之间相互转换。

MonetaryAmountFormatter用于MonetaryAmount和String之间格式化。

Jsr354NumberFormatAnnotationFormatterFactory处理@NumberFormat标注的字段。

DateTimeFormatterRegistrar().registerFormatters注册date和time类型的Formatter。

DateTimeFormatterRegistrar

public DateTimeFormatterRegistrar() {
	for (Type type : Type.values()) {
		this.factories.put(type, new DateTimeFormatterFactory());
	}
}
private enum Type {DATE, TIME, DATE_TIME}

DateTimeFormatterRegistrar.registerFormatters(FormatterRegistry registry)

public void registerFormatters(FormatterRegistry registry) {
	DateTimeConverters.registerConverters(registry);

	DateTimeFormatter df = getFormatter(Type.DATE);
	DateTimeFormatter tf = getFormatter(Type.TIME);
	DateTimeFormatter dtf = getFormatter(Type.DATE_TIME);

	// Efficient ISO_LOCAL_* variants for printing since they are twice as fast...

	registry.addFormatterForFieldType(LocalDate.class,
			new TemporalAccessorPrinter(
					df == DateTimeFormatter.ISO_DATE ? DateTimeFormatter.ISO_LOCAL_DATE : df),
			new TemporalAccessorParser(LocalDate.class, df));

	registry.addFormatterForFieldType(LocalTime.class,
			new TemporalAccessorPrinter(
					tf == DateTimeFormatter.ISO_TIME ? DateTimeFormatter.ISO_LOCAL_TIME : tf),
			new TemporalAccessorParser(LocalTime.class, tf));

	registry.addFormatterForFieldType(LocalDateTime.class,
			new TemporalAccessorPrinter(
					dtf == DateTimeFormatter.ISO_DATE_TIME ? DateTimeFormatter.ISO_LOCAL_DATE_TIME : dtf),
			new TemporalAccessorParser(LocalDateTime.class, dtf));

	registry.addFormatterForFieldType(ZonedDateTime.class,
			new TemporalAccessorPrinter(dtf),
			new TemporalAccessorParser(ZonedDateTime.class, dtf));

	registry.addFormatterForFieldType(OffsetDateTime.class,
			new TemporalAccessorPrinter(dtf),
			new TemporalAccessorParser(OffsetDateTime.class, dtf));

	registry.addFormatterForFieldType(OffsetTime.class,
			new TemporalAccessorPrinter(tf),
			new TemporalAccessorParser(OffsetTime.class, tf));

	registry.addFormatterForFieldType(Instant.class, new InstantFormatter());
	registry.addFormatterForFieldType(Period.class, new PeriodFormatter());
	registry.addFormatterForFieldType(Duration.class, new DurationFormatter());
	registry.addFormatterForFieldType(Year.class, new YearFormatter());
	registry.addFormatterForFieldType(Month.class, new MonthFormatter());
	registry.addFormatterForFieldType(YearMonth.class, new YearMonthFormatter());
	registry.addFormatterForFieldType(MonthDay.class, new MonthDayFormatter());

	registry.addFormatterForFieldAnnotation(new Jsr310DateTimeFormatAnnotationFormatterFactory());
}

增加date和time类型的Formatter。Jsr310DateTimeFormatAnnotationFormatterFactory处理@DateTimeFormat注解标注的字段。

JodaTimeFormatterRegistrar添加Joda类型的日期和时间。

DateFormatterRegistrar添加jdk 的Date,Calendar等的Formatter。

标签:converterRegistry,SpringMVC,addConverter,FormattingConversionServiceFactoryBean,
From: https://www.cnblogs.com/shigongp/p/16852218.html

相关文章

  • 自适应噪声抑制算法LMSmatlab源码
    %filterparametersM=20;%numberoftapsmu=0.05;%step-sizeparametere_max=200;%maximum#ofepochs%constantspi=3.14;Fs=0.02;%signalfrequencyF......
  • 爱上源码,重学Spring MVC深入
    1.1gradle搭建源码调试环境1)搭建gradle环境4个步骤1、File-New-Module选择java和web2、填写包信息3、存储路径2)增加起步依赖依赖的项目,直接复制粘贴上去1、对......
  • 直播网站程序源码,搜索框实现快速搜索功能
    直播网站程序源码,搜索框实现快速搜索功能module.exports=asyncfunction(params,context){ constdb=context.database const_=db.command letresult=......
  • 集合框架及源码解读
    为什么需要学习集合框架?集合:存放多个元素内容框架:底层封装好,提供简单的API给开发人员使用集合框架:JDK帮助我们封装好,可以直接简单使用集合下面让我们看一下这段代码pu......
  • 从源码分析 MySQL的多版本控制(MVCC)
    什么是MVCCMVCC,Multi-VersionConcurrencyControl,多版本并发控制。MVCC是一种并发控制的方法,一般在数据库管理系统中,实现对数据库的并发访问;在编程语言中实现事务内存。MV......
  • vue源码分析-插槽原理
    Vue组件的另一个重要概念是插槽,它允许你以一种不同于严格的父子关系的方式组合组件。插槽为你提供了一个将内容放置到新位置或使组件更通用的出口。这一节将围绕官网对插......
  • vue源码分析-挂载流程和模板编译
    前面几节我们从newVue创建实例开始,介绍了创建实例时执行初始化流程中的重要两步,配置选项的资源合并,以及响应式系统的核心思想,数据代理。在合并章节,我们对Vue丰富的选项......
  • 关于SpringMvc使用@RequstBody报错500的原因
    在使用SpringMvc框架接收前端数据添加到数据库时报500错误,@PostMappingpublicResultsave(@RequestBodyBookbook){booleanflag=bookService.save......
  • SpringMVC
    SpringMVC简述是基于spring的一个框架,实际上就是spring的一个模块,专门做web开发的。可理解为servlet的一个升级。web开发底层是servlet,框架是在servlet基础......
  • python基于django的自媒体分享展示平台(源码调试+讲解+文档)
    ......