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。

posted @ 2022-05-06 08:17  strongmore  阅读(1110)  评论(0编辑  收藏  举报