Spring原始碼分析之ConversionService
阿新 • • 發佈:2022-05-05
前言
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。