1. 程式人生 > >spring 官方文件的介面理解整理(三)型別轉換

spring 官方文件的介面理解整理(三)型別轉換

所有相關介面的uml圖:

一、spring中型別轉換裡面我開始看的時候覺得converter和formatter的功能很多疑問,先來分析這兩個介面:

 1、Converter.java

package org.springframework.core.convert.converter;

public interface Converter<S, T> {

    T convert(S source);
}

2、Formatter.java

package org.springframework.format;

public interface Formatter<T> extends Printer<T>, Parser<T> {
}

從上面可以看出formatter時繼承Printer、Parser介面

Printer.java

public interface Printer<T> {

    String print(T fieldValue, Locale locale);
}

Parser.java

public interface Parser<T> {

    T parse(String clientValue, Locale locale) throws ParseException;
}

首先coverter介面只有cover方法,兩個不同型別之間的互轉都是使用相同方法名稱的方法。Formatter將cover方法拆成print和parse兩個方法,兩個方法對於往返多了中間變數String,也就是Formatter是Converter功能的子集。官方文件描述Coverter介面是提供通用型別轉換,Formatter介面傳遞引數時多Locale屬性而且兩個方法於往返多了中間變數String,也就是可以根據使用者的語言喜好對結果產生影響並且之間的傳輸通常使用String(這兒多理解一下

),所以這樣設計兩個方法,Formatter大多數在貨幣(number)和日期上面使用。

二、看ConversionService介面的作用

ConversionService.java

package org.springframework.core.convert;

public interface ConversionService {

    boolean canConvert(Class<?> sourceType, Class<?> targetType);

    <T> T convert(Object source, Class<T> targetType);

    boolean canConvert(TypeDescriptor sourceType, TypeDescriptor targetType);

    Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor targetType);

}

ConversionService提供了和Converter.java相同方法名稱的方法,但是方法引數不同,並且有兩個,為什麼有兩個,因為這個時service,實現裡面儲存許多Converter的實現類的例項物件,通過這兩個引數查詢我們需要的Converter物件。另外提供測試需要的convert是否存在的兩個canConvert方法。

三、ConverterRegistry的作用

ConverterRegistry.java

package org.springframework.core.convert.converter;

public interface ConverterRegistry {

	void addConverter(Converter<?, ?> converter);

	
	<S, T> void addConverter(Class<S> sourceType, Class<T> targetType, Converter<? super S, ? extends T> converter);

	void addConverter(GenericConverter converter);

	
	void addConverterFactory(ConverterFactory<?, ?> factory);

	
	void removeConvertible(Class<?> sourceType, Class<?> targetType);

}

ConverterRegistry提供對Converter實現類的物件的註冊和刪除。

四、FormatterRegistry的作用

FormatterRegistry.java

package org.springframework.format;

public interface FormatterRegistry extends ConverterRegistry {

    void addFormatterForFieldType(Class<?> fieldType, Printer<?> printer, Parser<?> parser);

    void addFormatterForFieldType(Class<?> fieldType, Formatter<?> formatter);

    void addFormatterForFieldType(Formatter<?> formatter);

    void addFormatterForAnnotation(AnnotationFormatterFactory<?, ?> factory);
}

FormatterRegistry提供formatter註冊converter,它的key是ConvertiblePair物件。ConvertiblePair是fieldType的繫結的往返對。

ConvertiblePair相關程式碼在GenericConverter.java中:

package org.springframework.core.convert.converter;

import java.util.Set;

import org.springframework.core.convert.TypeDescriptor;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;

public interface GenericConverter {

	@Nullable
	Set<ConvertiblePair> getConvertibleTypes();

	@Nullable
	Object convert(@Nullable Object source, TypeDescriptor sourceType, TypeDescriptor targetType);


	final class ConvertiblePair {

		private final Class<?> sourceType;

		private final Class<?> targetType;

		public ConvertiblePair(Class<?> sourceType, Class<?> targetType) {
			Assert.notNull(sourceType, "Source type must not be null");
			Assert.notNull(targetType, "Target type must not be null");
			this.sourceType = sourceType;
			this.targetType = targetType;
		}

		public Class<?> getSourceType() {
			return this.sourceType;
		}

		public Class<?> getTargetType() {
			return this.targetType;
		}

		@Override
		public boolean equals(@Nullable Object other) {
			if (this == other) {
				return true;
			}
			if (other == null || other.getClass() != ConvertiblePair.class) {
				return false;
			}
			ConvertiblePair otherPair = (ConvertiblePair) other;
			return (this.sourceType == otherPair.sourceType && this.targetType == otherPair.targetType);
		}

		@Override
		public int hashCode() {
			return (this.sourceType.hashCode() * 31 + this.targetType.hashCode());
		}

		@Override
		public String toString() {
			return (this.sourceType.getName() + " -> " + this.targetType.getName());
		}
	}

}

五、FormatterRegistrar的作用:

FormatterRegistrar.java

package org.springframework.format;

public interface FormatterRegistrar {

    void registerFormatters(FormatterRegistry registry);
}

FormatterRegistrar為給定格式類別註冊多個相關轉換器和格式化程式時非常有用,例如日期格式(日期格式互相轉換有多個)。相關例子看DateFormatterRegistrar.java

六、Converter特有的介面

ConverterFactory.java

package org.springframework.core.convert.converter;

public interface ConverterFactory<S, R> {

    <T extends R> Converter<S, T> getConverter(Class<T> targetType);
}

主要對Converter進行工廠模式包裝,生成Converter例項物件。

GenericConverter.java

package org.springframework.core.convert.converter;

public interface GenericConverter {

    public Set<ConvertiblePair> getConvertibleTypes();

    Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor targetType);
}

該介面是對Converter介面的複雜情況使用的介面,其中多了getConvertibleTypes方法,獲取source和target兩個往返Field對應所有的Set<ConvertiblePair>,單個ConvertiblePair在ConversionService中是key,通過這個尋找需要的converter。

ConditionalConverter.java

public interface ConditionalConverter {

    boolean matches(TypeDescriptor sourceType, TypeDescriptor targetType);
}

有時,Converter只有在特定條件成立時才需要執行,那麼就需要使用這個介面的matches方法。那麼就有了

ConditionalGenericConverter.java

public interface ConditionalGenericConverter extends GenericConverter, ConditionalConverter {
}

七、Formatter的其它介面

AnnotationFormatterFactory.java

package org.springframework.format;

public interface AnnotationFormatterFactory<A extends Annotation> {

    Set<Class<?>> getFieldTypes();

    Printer<?> getPrinter(A annotation, Class<?> fieldType);

    Parser<?> getParser(A annotation, Class<?> fieldType);
}

ps:以上就是spring中“型別轉換”提供的所有常用介面。spring中也有例子,下篇繼續。如果無法理解,可以常看spring官方文件如果有錯誤,歡迎指出。