类型转换
之前在介绍bean的创建过程中,其中有一步是调用populateBean,来将BeanDefinition中的PropertyValue来设置到bean中
因为在xml中标签中指定的值都为字符串类型,所以需要进行类型转换,将字符串类型的值转换为bean对应属性的类型
在populateBean中最后会调用applyPropertyValues来将PropertyValue中的属性值设置到创建的bean实例中
// AbstractAutowireCapableBeanFactory
protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
if (pvs != null) {
applyPropertyValues(beanName, mbd, bw, pvs);
}
}
在调用applyPropertyValues的过程中,会遍历PropertyValues中的所有属性,然后调用convertForProperty进行类型转换
// AbstractAutowireCapableBeanFactory
protected void applyPropertyValues(String beanName, BeanDefinition mbd, BeanWrapper bw, PropertyValues pvs) {
// 省略
// 判断是否使用了自定义的类型转换器
// 如果没有指定,那么会使用BeanWrapper作为类型转换器
TypeConverter converter = getCustomTypeConverter();
if (converter == null) {
converter = bw;
}
List<PropertyValue> deepCopy = new ArrayList<>(original.size());
boolean resolveNecessary = false;
for (PropertyValue pv : original) {
// 如果已经转换过,直接添加到deepCopy中
if (pv.isConverted()) {
deepCopy.add(pv);
}
else {
String propertyName = pv.getName();
Object originalValue = pv.getValue();
if (originalValue == AutowiredPropertyMarker.INSTANCE) {
Method writeMethod = bw.getPropertyDescriptor(propertyName).getWriteMethod();
if (writeMethod == null) {
throw new IllegalArgumentException("Autowire marker for property without write method: " + pv);
}
originalValue = new DependencyDescriptor(new MethodParameter(writeMethod, 0), true);
}
Object resolvedValue = valueResolver.resolveValueIfNecessary(pv, originalValue);
Object convertedValue = resolvedValue;
boolean convertible = bw.isWritableProperty(propertyName) &&
!PropertyAccessorUtils.isNestedOrIndexedProperty(propertyName);
if (convertible) {
// 进行转换
convertedValue = convertForProperty(resolvedValue, propertyName, bw, converter);
}
// Possibly store converted value in merged bean definition,
// in order to avoid re-conversion for every created bean instance.
if (resolvedValue == originalValue) {
if (convertible) {
pv.setConvertedValue(convertedValue);
}
deepCopy.add(pv);
}
else if (convertible && originalValue instanceof TypedStringValue &&
!((TypedStringValue) originalValue).isDynamic() &&
!(convertedValue instanceof Collection || ObjectUtils.isArray(convertedValue))) {
pv.setConvertedValue(convertedValue);
deepCopy.add(pv);
}
else {
resolveNecessary = true;
deepCopy.add(new PropertyValue(pv, convertedValue));
}
}
}
}
下面主要看下convertForProperty做了什么
private Object convertForProperty(
@Nullable Object value, String propertyName, BeanWrapper bw, TypeConverter converter) {
// 如果传入的Converter是BeanWrapperImpl,那么会调用BeanWrapperImpl的convertForProperty来进行类型的转换
if (converter instanceof BeanWrapperImpl) {
return ((BeanWrapperImpl) converter).convertForProperty(value, propertyName);
}
else {
// 否则会调用TypeConvertor的convertIfNecessary来进行类型的转换
PropertyDescriptor pd = bw.getPropertyDescriptor(propertyName);
MethodParameter methodParam = BeanUtils.getWriteMethodParameter(pd);
return converter.convertIfNecessary(value, pd.getPropertyType(), methodParam);
}
}
TypeConverter.convertIfNecessary
下面首先看下走TypeConverter.convertIfNecessary这个分支
convertIfNecessary方法主要由DateBinder和TypeConverterSupport两个类来实现,这里主要看下TypeConverterSupport
// TypeConverterSupport
public <T> T convertIfNecessary(@Nullable Object value, @Nullable Class<T> requiredType,
@Nullable TypeDescriptor typeDescriptor) throws TypeMismatchException {
Assert.state(this.typeConverterDelegate != null, "No TypeConverterDelegate");
try {
return this.typeConverterDelegate.convertIfNecessary(null, null, value, requiredType, typeDescriptor);
}
catch (ConverterNotFoundException | IllegalStateException ex) {
throw new ConversionNotSupportedException(value, requiredType, ex);
}
catch (ConversionException | IllegalArgumentException ex) {
throw new TypeMismatchException(value, requiredType, ex);
}
}
可以看到主要是调用TypeConverterDelegate的convertIfNecessary来完成的
BeanWrapperImpl.convertForProperty
// BeanWrapperImpl
public Object convertForProperty(@Nullable Object value, String propertyName) throws TypeMismatchException {
// 在进行属性转换之前,增加了对PropertyDescriptor和TypeDescriptor的缓存
CachedIntrospectionResults cachedIntrospectionResults = getCachedIntrospectionResults();
PropertyDescriptor pd = cachedIntrospectionResults.getPropertyDescriptor(propertyName);
if (pd == null) {
throw new InvalidPropertyException(getRootClass(), getNestedPath() + propertyName,
"No property '" + propertyName + "' found");
}
TypeDescriptor td = cachedIntrospectionResults.getTypeDescriptor(pd);
if (td == null) {
td = cachedIntrospectionResults.addTypeDescriptor(pd, new TypeDescriptor(property(pd)));
}
// 执行类型转换
return convertForProperty(propertyName, null, value, td);
}
// AbstractNestablePropertyAccessor
protected Object convertForProperty(
String propertyName, @Nullable Object oldValue, @Nullable Object newValue, TypeDescriptor td)
throws TypeMismatchException {
return convertIfNecessary(propertyName, oldValue, newValue, td.getType(), td);
}
// AbstractNestablePropertyAccessoor
private Object convertIfNecessary(@Nullable String propertyName, @Nullable Object oldValue,
@Nullable Object newValue, @Nullable Class<?> requiredType, @Nullable TypeDescriptor td)
throws TypeMismatchException {
Assert.state(this.typeConverterDelegate != null, "No TypeConverterDelegate");
try {
// 最终也会交给TypeConverterDelegate进行类型转换
return this.typeConverterDelegate.convertIfNecessary(propertyName, oldValue, newValue, requiredType, td);
}
catch (ConverterNotFoundException | IllegalStateException ex) {
PropertyChangeEvent pce =
new PropertyChangeEvent(getRootInstance(), this.nestedPath + propertyName, oldValue, newValue);
throw new ConversionNotSupportedException(pce, requiredType, ex);
}
catch (ConversionException | IllegalArgumentException ex) {
PropertyChangeEvent pce =
new PropertyChangeEvent(getRootInstance(), this.nestedPath + propertyName, oldValue, newValue);
throw new TypeMismatchException(pce, requiredType, ex);
}
}
可以看到,不管走哪个分支,最终都会交给TypeConverterDelegate进行类型转换
TypeConverterDelegate.convertIfNecessary
public <T> T convertIfNecessary(@Nullable String propertyName, @Nullable Object oldValue, @Nullable Object newValue,
@Nullable Class<T> requiredType, @Nullable TypeDescriptor typeDescriptor) throws IllegalArgumentException {
// Custom editor for this type?
// 判断是否有合适的自定义editor
PropertyEditor editor = this.propertyEditorRegistry.findCustomEditor(requiredType, propertyName);
ConversionFailedException conversionAttemptEx = null;
// No custom editor but custom ConversionService specified?
ConversionService conversionService = this.propertyEditorRegistry.getConversionService();
// 如果没有合适的自定义editor,并且conversionService不为空,那么使用conversionService进行类型转换
if (editor == null && conversionService != null && newValue != null && typeDescriptor != null) {
TypeDescriptor sourceTypeDesc = TypeDescriptor.forObject(newValue);
if (conversionService.canConvert(sourceTypeDesc, typeDescriptor)) {
try {
return (T) conversionService.convert(newValue, sourceTypeDesc, typeDescriptor);
}
catch (ConversionFailedException ex) {
// fallback to default conversion logic below
conversionAttemptEx = ex;
}
}
}
// 省略
}
从上面的代码可以看出TypeConverterDelegate最终调用ConversionService的convert方法来进行类型的转换
而ConversionService的convert方法又是由GenericConversionService来实现的
GenericConversionService.convert
// GenericConversionService
public Object convert(@Nullable Object source, @Nullable TypeDescriptor sourceType, TypeDescriptor targetType) {
Assert.notNull(targetType, "Target type to convert to cannot be null");
// <1> 如果源类型为null,则待转换的值也必须为null
// 这里会判断目标类型是否是Optional,如果是,则会返回Optional.empty(),否则直接返回null
if (sourceType == null) {
Assert.isTrue(source == null, "Source must be [null] if source type == [null]");
return handleResult(null, targetType, convertNullSource(null, targetType));
}
// <2> 属性值和源类型不一致,直接抛出异常
if (source != null && !sourceType.getObjectType().isInstance(source)) {
throw new IllegalArgumentException("Source to convert from must be an instance of [" +
sourceType + "]; instead it was a [" + source.getClass().getName() + "]");
}
// <3> 根据源类型和目标类型获取对应的GenericConverter
GenericConverter converter = getConverter(sourceType, targetType);
if (converter != null) {
// 使用GenericConverter来进行类型转换
Object result = ConversionUtils.invokeConverter(converter, source, sourceType, targetType);
return handleResult(sourceType, targetType, result);
}
return handleConverterNotFound(source, sourceType, targetType);
}
handlerResult
handlerResult的作用就是对最终转换之后的结果进行校验
// GenericConversionService
private Object handleResult(@Nullable TypeDescriptor sourceType, TypeDescriptor targetType, @Nullable Object result) {
// 如果结果是null,会判断目标类型是否是基础类型,如果是基础类型直接抛出异常,因为基础类型无法接收null
if (result == null) {
assertNotPrimitiveTargetType(sourceType, targetType);
}
return result;
}
convertNullSource
convertNullSource对源类型为null情况的处理,这里会根据目标类型是否是Optional,来决定返回Optional.empty还是null
protected Object convertNullSource(@Nullable TypeDescriptor sourceType, TypeDescriptor targetType) {
if (targetType.getObjectType() == Optional.class) {
return Optional.empty();
}
return null;
}
handleConverterNotFound
hnadlerConverterNotFound用来处理没有合适Converter的情况
// GenericConversionService
private Object handleConverterNotFound(
@Nullable Object source, @Nullable TypeDescriptor sourceType, TypeDescriptor targetType) {
// 属性值为null
if (source == null) {
assertNotPrimitiveTargetType(sourceType, targetType);
return null;
}
// 源类型可以转换成目标类型
if ((sourceType == null || sourceType.isAssignableTo(targetType)) &&
targetType.getObjectType().isInstance(source)) {
return source;
}
throw new ConverterNotFoundException(sourceType, targetType);
}
getConverter
getConverter的主要作用是根据源类型和目标类型来获取合适的GenericConverter
// GenericConversionService
protected GenericConverter getConverter(TypeDescriptor sourceType, TypeDescriptor targetType) {
// <1> 使用源类型和目标类型来生成缓存key,如果缓存中有,直接返回缓存中对应的GenericConverter
ConverterCacheKey key = new ConverterCacheKey(sourceType, targetType);
GenericConverter converter = this.converterCache.get(key);
if (converter != null) {
return (converter != NO_MATCH ? converter : null);
}
// <2> 如果缓存中不存在,那么会从Converters中寻找合适的GenericConverter
converter = this.converters.find(sourceType, targetType);
if (converter == null) {
converter = getDefaultConverter(sourceType, targetType);
}
// <3> 将找到的GenericConverter放入缓存
if (converter != null) {
this.converterCache.put(key, converter);
return converter;
}
this.converterCache.put(key, NO_MATCH);
return null;
}
Converters
Converters用来维护所有注册进来的GenericConverter
其中有两个属性用来维护注册进来的converter
// 用来维护全局converter
private final Set<GenericConverter> globalConverters = new CopyOnWriteArraySet<>();
private final Map<ConvertiblePair, ConvertersForPair> converters = new ConcurrentHashMap<>(256);
// Converters
public GenericConverter find(TypeDescriptor sourceType, TypeDescriptor targetType) {
// Search the full type hierarchy
// 分别获得源类型和目标类型的类继承层次中的类
List<Class<?>> sourceCandidates = getClassHierarchy(sourceType.getType());
List<Class<?>> targetCandidates = getClassHierarchy(targetType.getType());
// 分别使用源类型和目标类型类继承层次中的类来生成ConvertiblePair,在注册进来的converter中进行查找
for (Class<?> sourceCandidate : sourceCandidates) {
for (Class<?> targetCandidate : targetCandidates) {
ConvertiblePair convertiblePair = new ConvertiblePair(sourceCandidate, targetCandidate);
GenericConverter converter = getRegisteredConverter(sourceType, targetType, convertiblePair);
if (converter != null) {
return converter;
}
}
}
return null;
}
// Converters
private GenericConverter getRegisteredConverter(TypeDescriptor sourceType,
TypeDescriptor targetType, ConvertiblePair convertiblePair) {
// Check specifically registered converters
// 分别从converters和globalConverters中进行查找
// <1> 从converters中进行查找,首先根据源类型和目标类型,构建convertiblePair
// 根据convertiblePair找到对应的ConvertersForPair,再从ConvertersForPair中找到合适的converter
ConvertersForPair convertersForPair = this.converters.get(convertiblePair);
if (convertersForPair != null) {
GenericConverter converter = convertersForPair.getConverter(sourceType, targetType);
if (converter != null) {
return converter;
}
}
// Check ConditionalConverters for a dynamic match
// <2> 从全局converters中查找,则是遍历每个converter,然后调用match,判断是否可以支持当前源类型和目标类型的转换
for (GenericConverter globalConverter : this.globalConverters) {
if (((ConditionalConverter) globalConverter).matches(sourceType, targetType)) {
return globalConverter;
}
}
return null;
}
ConversionUtils.invokeConverter
使用找到的GenericConverter对属性进行转换
// ConversionUtils
public static Object invokeConverter(GenericConverter converter, @Nullable Object source,
TypeDescriptor sourceType, TypeDescriptor targetType) {
try {
return converter.convert(source, sourceType, targetType);
}
catch (ConversionFailedException ex) {
throw ex;
}
catch (Throwable ex) {
throw new ConversionFailedException(sourceType, targetType, source, ex);
}
}
Converter注册
GenericConversionService有多个重载的addConverter以及一个addConverterFactory
addConverter(Class, Class,Converter<S super S,T extends T>)
// GenericConversionService
public <S, T> void addConverter(Class<S> sourceType, Class<T> targetType, Converter<? super S, ? extends T> converter) {
addConverter(new ConverterAdapter(
converter, ResolvableType.forClass(sourceType), ResolvableType.forClass(targetType)));
}
public void addConverter(GenericConverter converter) {
this.converters.add(converter);
invalidateCache();
}
addConverter(Converter<?,?>)
public void addConverter(Converter<?, ?> converter) {
// 获取当前converter的泛型
ResolvableType[] typeInfo = getRequiredTypeInfo(converter.getClass(), Converter.class);
if (typeInfo == null && converter instanceof DecoratingProxy) {
typeInfo = getRequiredTypeInfo(((DecoratingProxy) converter).getDecoratedClass(), Converter.class);
}
if (typeInfo == null) {
throw new IllegalArgumentException("Unable to determine source type <S> and target type <T> for your " +
"Converter [" + converter.getClass().getName() + "]; does the class parameterize those types?");
}
addConverter(new ConverterAdapter(converter, typeInfo[0], typeInfo[1]));
}
public void addConverter(GenericConverter converter) {
this.converters.add(converter);
invalidateCache();
}
addConverterFactory(ConverterFactory<?,?>)
public void addConverterFactory(ConverterFactory<?, ?> factory) {
// 获取factory的泛型
ResolvableType[] typeInfo = getRequiredTypeInfo(factory.getClass(), ConverterFactory.class);
if (typeInfo == null && factory instanceof DecoratingProxy) {
typeInfo = getRequiredTypeInfo(((DecoratingProxy) factory).getDecoratedClass(), ConverterFactory.class);
}
if (typeInfo == null) {
throw new IllegalArgumentException("Unable to determine source type <S> and target type <T> for your " +
"ConverterFactory [" + factory.getClass().getName() + "]; does the class parameterize those types?");
}
addConverter(new ConverterFactoryAdapter(factory,
new ConvertiblePair(typeInfo[0].toClass(), typeInfo[1].toClass())));
}
public void addConverter(GenericConverter converter) {
this.converters.add(converter);
invalidateCache();
}
addConverter(GenericConverter)
// GenericConversionService
public void addConverter(GenericConverter converter) {
this.converters.add(converter);
invalidateCache();
}
可以看到上面不同形式添加converter的方法,最终都是创建GenericConverter的实现类的实例,然后调用当前这个addConverter进行converter注册操作的,不同的是,如果入参是Converter,那么会创建ConverterAdapter;如果入参是ConverterFactory,那么会创建ConverterFactoryAdapter
接着看下Converters的add方法
// Converters
public void add(GenericConverter converter) {
// <1> 获取当前converter的ConvertiblePair
Set<ConvertiblePair> convertibleTypes = converter.getConvertibleTypes();
// <2> 如果为空,加入到全局converter中
if (convertibleTypes == null) {
Assert.state(converter instanceof ConditionalConverter,
"Only conditional converters may return null convertible types");
this.globalConverters.add(converter);
}
else {
// <3> 根据当前ConvertiblePair找到已有的ConvertersPair,然后将当前converter添加进去
// 一个ConvertersForPair中包含多个GenericConverter
for (ConvertiblePair convertiblePair : convertibleTypes) {
getMatchableConverters(convertiblePair).add(converter);
}
}
}
DefaultConversionService
DefaultConversionService是GenericConversionService的默认实现类,主要的作用就是注册一些默认的converter
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));
}
注册自定义Converter
spring提供了ConversionServiceFactoryBean来支持自定义Converter
// ConversionServiceFactoryBean
public class ConversionServiceFactoryBean implements FactoryBean<ConversionService>, InitializingBean {
@Nullable
private Set<?> converters;
@Nullable
private GenericConversionService conversionService;
/**
* Configure the set of custom converter objects that should be added:
* implementing {@link org.springframework.core.convert.converter.Converter},
* {@link org.springframework.core.convert.converter.ConverterFactory},
* or {@link org.springframework.core.convert.converter.GenericConverter}.
*/
public void setConverters(Set<?> converters) {
this.converters = converters;
}
@Override
public void afterPropertiesSet() {
// 创建DefaultConversionService
this.conversionService = createConversionService();
// 遍历convertes,将其中的每个converter注册到conversionService中
ConversionServiceFactory.registerConverters(this.converters, this.conversionService);
}
/**
* Create the ConversionService instance returned by this factory bean.
* <p>Creates a simple {@link GenericConversionService} instance by default.
* Subclasses may override to customize the ConversionService instance that
* gets created.
*/
protected GenericConversionService createConversionService() {
return new DefaultConversionService();
}
// implementing FactoryBean
@Override
@Nullable
public ConversionService getObject() {
return this.conversionService;
}
@Override
public Class<? extends ConversionService> getObjectType() {
return GenericConversionService.class;
}
@Override
public boolean isSingleton() {
return true;
}
}
为了注册我们自己的converter,只需要在创建ConversionServiceFactoryBean的时候,通过setConverters方法将我们自己定义的converter注册进去即可