在上篇文章中小編分析了 Spring ConversionService 型別轉換體系,相信各位都對其有了一個清晰的認識,這篇部落格將利用 ConversionService 體系來實現自己的型別轉換器。
ConversionService 是 Spring 型別轉換器體系中的核心介面,它定義了是否可以完成轉換( canConvert()
) 與 型別轉換( convert()
)兩類介面。ConversionService 有三個子類,每個子類針對不同的型別轉換:
- Converter
:將 S 型別物件轉為 T 型別物件。 - GenericConverter:會根據源類物件及標的類物件所在的宿主類中的背景關係資訊進行型別轉換。
- ConverterFactory:將相同系列多個 “同質” Converter 封裝在一起。如果希望將一種型別的物件轉換為另一種型別及其子類的物件(例如將 String 轉換為 Number 及 Number 子類(Integer、Long、Double 等)物件)可使用該轉換器工廠類。
如何自定義型別轉換器?分兩步走:
- 實現 Converter / GenericConverter / ConverterFactory 介面
- 將該類註冊到 ConversionServiceFactoryBean 中。
ConversionServiceFactoryBean 實現了 InitializingBean 介面實現 afterPropertiesSet()
,我們知道在 Bean 實體化 bean 階段,Spring 容器會檢查當前 bean 是否實現了 InitializingBean 介面,如果是則執行相應的初始化方法。(關於 InitializingBean 詳情請參考:【死磕 Spring】—– IOC 之 深入分析 InitializingBean 和 init-method)。 afterPropertiesSet()
原始碼如下:
public void afterPropertiesSet() {
this.conversionService = createConversionService();
ConversionServiceFactory.registerConverters(this.converters, this.conversionService);
}
首先呼叫 createConversionService()
初始化 conversionService,然後呼叫 ConversionServiceFactory.registerConverters()
將定義的 converters 註入到型別轉換體系中。 createConversionService()
其實就是建立一個 DefaultConversionService 實體物件,對於 DefaultConversionService 小編在上篇部落格已經分析了,如有不瞭解的請移步上篇博文。這裡直接分析 ConversionServiceFactory.registerConverters()
,該方法是將定義的 converter 註冊到標的 ConverterRegistry 中,我們知道 ConverterRegistry 是一個 Converter 註冊器,他定義了一系列註冊方法。
public static void registerConverters(@Nullable Set> converters, ConverterRegistry registry) {
if (converters != null) {
for (Object converter : converters) {
if (converter instanceof GenericConverter) {
registry.addConverter((GenericConverter) converter);
}
else if (converter instanceof Converter, ?>) {
registry.addConverter((Converter, ?>) converter);
}
else if (converter instanceof ConverterFactory, ?>) {
registry.addConverterFactory((ConverterFactory, ?>) converter);
}
else {
throw new IllegalArgumentException("Each converter object must implement one of the " +
"Converter, ConverterFactory, or GenericConverter interfaces");
}
}
}
}
呼叫 ConverterRegistry 的 addConverter()
方法將轉換器註冊到容器中。所以在我們使用 Spring 容器的時候,Spring 將會自動識別出 IOC 容器中註冊的 ConversionService 並且在 bean 屬性註入階段使用自定義的轉換器完成屬性的轉換了。
實體
定義 StudentConversionService 轉換器:
public class StudentConversionService implements Converter<String,StudentService>{
@Override
public StudentService convert(String source) {
if(StringUtils.hasLength(source)){
String[] sources = source.split("#");
StudentService studentService = new StudentService();
studentService.setAge(Integer.parseInt(sources[0]));
studentService.setName(sources[1]);
return studentService;
}
return null;
}
}
配置:
id="conversionService"
class="org.springframework.context.support.ConversionServiceFactoryBean">
name="converters">
bean="studentConversionService"/>
id="studentConversionService" class="org.springframework.core.conversion.StudentConversionService"/>
id="student" class="org.springframework.core.conversion.Student">
name="studentService" value="18#chenssy"/>