SpringMVC源码-创建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。

原文地址:http://www.cnblogs.com/shigongp/p/16852218.html

发表评论

您的电子邮箱地址不会被公开。