Spring源码分析之ConversionService
前言
ConversionService表示类型转换服务,如将字符串转换为Long,字符串转换为日期等。在处理属性和创建Bean对象等很多场景都会使用到。
ConversionService
相关类图如下
默认实现为DefaultConversionService,默认增加了很多类型转换器,如字符串转为集合。
import org.springframework.core.convert.ConversionService;
import org.springframework.core.convert.support.DefaultConversionService;
public class Client {
public static void main(String[] args) {
ConversionService sharedInstance = DefaultConversionService.getSharedInstance();
System.out.println(sharedInstance);//查看所有Converter
System.out.println(sharedInstance.canConvert(String.class, Integer.class));
System.out.println(sharedInstance.convert("123", Integer.class));
}
}
DefaultConversionService使用双重锁判断来实现单例,不仅实现了ConversionService接口(类型转换),,也实现了ConverterRegistry接口(注册表,可以增加转换器)。
配置自定义类型转换器
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import lombok.ToString;
import org.springframework.core.convert.converter.Converter;
import org.springframework.core.convert.support.DefaultConversionService;
public class TestCustomConverter {
public static void main(String[] args) {
DefaultConversionService sharedInstance = (DefaultConversionService) DefaultConversionService
.getSharedInstance();
sharedInstance.addConverter(new StringToUserConverter());
User user = sharedInstance.convert("lisi", User.class);
System.out.println(user);//TestCustomConverter.User(name=lisi)
}
@Getter
@Setter
@ToString
@AllArgsConstructor
@NoArgsConstructor
public static class User {
private String name;
}
public static class StringToUserConverter implements Converter<String, User> {
@Override
public User convert(String source) {
return new User(source);
}
}
}
自定义类型转换器需要实现Converter接口,第一个泛型表示源类型,第二个表示目标类型。
Spring中配置ConversionService
import java.util.HashSet;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.support.ConversionServiceFactoryBean;
@Configuration
public class BeanConfig {
@Bean("conversionService")
public ConversionServiceFactoryBean conversionServiceFactoryBean() {
ConversionServiceFactoryBean factoryBean = new ConversionServiceFactoryBean();
//可以在这里添加自定义类型转换器
factoryBean.setConverters(new HashSet<>());
return factoryBean;
}
}
使用JavaConfig的方式来配置Bean,ConversionServiceFactoryBean底层实现也是DefaultConversionService。
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.core.convert.ConversionService;
public class TestConversionServiceConfig {
public static void main(String[] args) {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(
BeanConfig.class);
ConversionService conversionService = context.getBeanFactory().getConversionService();
System.out.println(conversionService.convert("123", Integer.class));//123
}
}
注意配置的ConversionServiceFactoryBean的Bean名称必须为conversionService,这是因为BeanFactory会查找类型为ConversionService且名称为conversionService的Bean。
SpringBoot配置自定义Converter
SpringBoot会自动配置ConversionService对象,实现类为ApplicationConversionService(包含更多的类型转换器)。
import org.springframework.context.annotation.Configuration;
import org.springframework.format.FormatterRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Override
public void addFormatters(FormatterRegistry registry) {
registry.addConverter(new StringToUserConverter());
}
}
SpringBoot也会将所有实现Converter接口的Bean添加到ConverterRegistry。