序言
经过前面一系列的加载、解析等准备工作,此刻refresh方法的执行已经来到了尾声,接下来我们用几篇文章着重的介绍一下Bean的初始化
代码
着重看refresh()主流程
中的finishBeanFactoryInitialization()
方法。
finishBeanFactoryInitialization
方法首先会判断beanFactory中是否包含ConversionService,并设置属性。
java
protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
// Initialize conversion service for this context.
// 如果包含ConversionService,则赋值给conversionService变量
if (beanFactory.containsBean(CONVERSION_SERVICE_BEAN_NAME) &&
beanFactory.isTypeMatch(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class)) {
beanFactory.setConversionService(
beanFactory.getBean(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class));
}
//省略部分源码...
}
扩展:ConversionService
我们经常会在页面进行各种各样的输入 abcd,1234等 这些输入是如何变换成指定的类型的呢?。
看看beanFacroty设置的ConversionService是什么?如果我们想要自定义ConversionService改如何实现?
ConversionService
Spring的提供的ConversionService接口,里面包含判断canConvert()
方法判断是否可以进行类型转换,convert
方法进行类型的转换。接口的实现类有很多,我们主要看DefaultConversionService
即可。
java
/**
* 类型转换服务
*/
public interface ConversionService {
/**
* 判断sourceType是否能转换成targetType
*/
boolean canConvert(@Nullable Class<?> sourceType, Class<?> targetType);
boolean canConvert(@Nullable TypeDescriptor sourceType, TypeDescriptor targetType);
@Nullable
<T> T convert(@Nullable Object source, Class<T> targetType);
@Nullable
Object convert(@Nullable Object source, @Nullable TypeDescriptor sourceType, TypeDescriptor targetType);
}
DefaultConversionService
DefaultConversionService
下分别有addDefaultConverters
、addCollectionConverters
、addScalarConverters
三个方法,会在DefaultConversionService初始化时添加各种类型的Converter,以便我们使用时直接拿。我们看一下源码:
java
public class DefaultConversionService extends GenericConversionService {
@Nullable
private static volatile DefaultConversionService sharedInstance;
public DefaultConversionService() {
addDefaultConverters(this);
}
public static void addDefaultConverters(ConverterRegistry converterRegistry) {
addScalarConverters(converterRegistry);
addCollectionConverters(converterRegistry);
converterRegistry.addConverter(new StringToTimeZoneConverter());
//添加各种Converter。。。。
}
public static void addCollectionConverters(ConverterRegistry converterRegistry) {
ConversionService conversionService = (ConversionService) converterRegistry;
converterRegistry.addConverter(new ArrayToCollectionConverter(conversionService));
//添加各种Converter。。。。
}
private static void addScalarConverters(ConverterRegistry converterRegistry) {
//省略部分源码
converterRegistry.addConverterFactory(new StringToNumberConverterFactory());
//添加各种ConverterFacroty。。。。
}
}
Converter接口
addDefaultConverters方法。
StrinToimeZoneConverter
类继承了Converter,而Converter接口中的convert方法会将参数S 转换成 T类型
。
java
class StringToTimeZoneConverter implements Converter<String, TimeZone> {
@Override
public TimeZone convert(String source) {
return StringUtils.parseTimeZoneString(source);
}
}
@FunctionalInterface
public interface Converter<S, T> {
/** S 转换成 T类型
* Convert the source object of type {@code S} to target type {@code T}.
* @param source the source object to convert, which must be an instance of {@code S} (never {@code null})
* @return the converted object, which must be an instance of {@code T} (potentially {@code null})
* @throws IllegalArgumentException if the source cannot be converted to the desired target type
*/
@Nullable
T convert(S source);
}
ConditionalGenericConverter
addCollectionConverters方法。
ArrayToCollectionConverter
类继承关系
ArrayToCollectionConverter -》ConditionalGenericConverter -》 GenericConverter(ConditionalConverter)
。
其中ConditionalConverter
接口中的match方法可以理解成@Confitional注解,根据传入的 sourceType 和 targetType 来判断是否符合转换。
而GenericConverter
中的convert
方法,会将 source 通过 sourceType的描述 转换成 targetType类型。
java
final class ArrayToCollectionConverter implements ConditionalGenericConverter {
@Override
public Set<ConvertiblePair> getConvertibleTypes() {
return Collections.singleton(new ConvertiblePair(Object[].class, Collection.class));
}
@Override
public boolean matches(TypeDescriptor sourceType, TypeDescriptor targetType) {
return ConversionUtils.canConvertElements(
sourceType.getElementTypeDescriptor(), targetType.getElementTypeDescriptor(), this.conversionService);
}
public Object convert(@Nullable Object source, TypeDescriptor sourceType, TypeDescriptor targetType) {
// 。。。。。。。省略
}
}
java
public interface ConditionalGenericConverter extends GenericConverter, ConditionalConverter {
}
java
public interface ConditionalConverter {
boolean matches(TypeDescriptor sourceType, TypeDescriptor targetType);
}
java
public interface GenericConverter {
/**
* Return the source and target types that this converter can convert between.
* <p>Each entry is a convertible source-to-target type pair.
* <p>For {@link ConditionalConverter conditional converters} this method may return
* {@code null} to indicate all source-to-target pairs should be considered.
*/
@Nullable
Set<ConvertiblePair> getConvertibleTypes();
/**
* Convert the source object to the targetType described by the {@code TypeDescriptor}.
* @param source the source object to convert (may be {@code null})
* @param sourceType the type descriptor of the field we are converting from
* @param targetType the type descriptor of the field we are converting to
* @return the converted object
*/
@Nullable
Object convert(@Nullable Object source, TypeDescriptor sourceType, TypeDescriptor targetType);
/**
* suorceType 和 targetType的键值对
* Holder for a source-to-target class pair.
*/
final class ConvertiblePair {
private final Class<?> sourceType;
private final Class<?> targetType;
public ConvertiblePair(Class<?> sourceType, Class<?> targetType) {
this.sourceType = sourceType;
this.targetType = targetType;
}
public Class<?> getSourceType() {
return this.sourceType;
}
public Class<?> getTargetType() {
return this.targetType;
}
}
}
TypeDescriptor
包含常见基础的类型类和包装类。
java
public class TypeDescriptor implements Serializable {
private static final Annotation[] EMPTY_ANNOTATION_ARRAY = new Annotation[0];
private static final Map<Class<?>, TypeDescriptor> commonTypesCache = new HashMap<>(32);
private static final Class<?>[] CACHED_COMMON_TYPES = {
boolean.class, Boolean.class, byte.class, Byte.class, char.class, Character.class,
double.class, Double.class, float.class, Float.class, int.class, Integer.class,
long.class, Long.class, short.class, Short.class, String.class, Object.class};
static {
for (Class<?> preCachedClass : CACHED_COMMON_TYPES) {
commonTypesCache.put(preCachedClass, valueOf(preCachedClass));
}
}
}
ConverterFactory
StringToNumberConverterFactory
java
final class StringToNumberConverterFactory implements ConverterFactory<String, Number> {
@Override
public <T extends Number> Converter<String, T> getConverter(Class<T> targetType) {
return new StringToNumber<>(targetType);
}
private static final class StringToNumber<T extends Number> implements Converter<String, T> {
private final Class<T> targetType;
public StringToNumber(Class<T> targetType) {
this.targetType = targetType;
}
@Override
public T convert(String source) {
if (source.isEmpty()) {
return null;
}
return NumberUtils.parseNumber(source, this.targetType);
}
}
}
ConverterFactory
ConverterFactory转换会支持将 S 转换成 T 类型 (T instance of R)。
java
public interface ConverterFactory<S, R> {
/**
* 获取转换器
*
* Get the converter to convert from S to target type T, where T is also an instance of R.
* @param <T> the target type
* @param targetType the target type to convert to
* @return a converter from S to T
*/
<T extends R> Converter<S, T> getConverter(Class<T> targetType);
}